@intentius/chant-lexicon-otel 0.97.0 → 0.99.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 +5 -0
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/components/common.d.ts +7 -2
- package/dist/components/common.d.ts.map +1 -1
- package/dist/components/filtering.d.ts +58 -1
- package/dist/components/filtering.d.ts.map +1 -1
- package/dist/components/processors.d.ts +10 -0
- package/dist/components/processors.d.ts.map +1 -1
- package/dist/components/receivers.d.ts +87 -7
- package/dist/components/receivers.d.ts.map +1 -1
- package/dist/import/embedded.d.ts +12 -0
- package/dist/import/embedded.d.ts.map +1 -0
- package/dist/import/generator.d.ts +39 -0
- package/dist/import/generator.d.ts.map +1 -0
- package/dist/import/parser.d.ts +61 -0
- package/dist/import/parser.d.ts.map +1 -0
- package/dist/integrity.json +4 -4
- package/dist/lint/rules/literal-credential.d.ts.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/rules/literal-credential.ts +46 -17
- package/dist/skills/chant-otel.md +11 -0
- package/package.json +2 -2
- package/src/codegen/docs.ts +2 -1
- package/src/components/common.ts +7 -2
- package/src/components/filtering.test.ts +27 -0
- package/src/components/filtering.ts +65 -2
- package/src/components/processors.ts +4 -0
- package/src/components/receivers.ts +88 -4
- package/src/import/embedded.test.ts +56 -0
- package/src/import/embedded.ts +41 -0
- package/src/import/generated-types.e2e.test.ts +110 -0
- package/src/import/generator.test.ts +165 -0
- package/src/import/generator.ts +509 -0
- package/src/import/parser.test.ts +174 -0
- package/src/import/parser.ts +236 -0
- package/src/import/roundtrip.test.ts +365 -0
- package/src/import/testdata/agent-observability-agent.yaml +54 -0
- package/src/import/testdata/agent-observability-gateway.yaml +128 -0
- package/src/import/testdata/fixtures.ts +274 -0
- package/src/import/testdata/gateway.yaml +153 -0
- package/src/import/testdata/upstream/couchbase.yaml +150 -0
- package/src/import/testdata/upstream/fault-tolerant-logs.yaml +27 -0
- package/src/import/testdata/upstream/kubernetes-filelog.yaml +86 -0
- package/src/import/testdata/upstream/loadbalancing-agent.yaml +38 -0
- package/src/import/testdata/upstream/loadbalancing-backend.yaml +27 -0
- package/src/import/testdata/upstream/logline-filter-in.yaml +20 -0
- package/src/import/testdata/upstream/logline-filter-out.yaml +20 -0
- package/src/import/testdata/upstream/secure-tracing.yaml +26 -0
- package/src/import/testdata/upstream/servicegraph-nop.yaml +28 -0
- package/src/lint/rules/literal-credential.ts +46 -17
- package/src/lint/rules/rules.test.ts +16 -0
- package/src/plugin.ts +15 -0
- package/src/skills/chant-otel.md +11 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Vendored from opentelemetry-collector-contrib v0.130.0 (Apache-2.0), unchanged below this header:
|
|
2
|
+
# https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.130.0/exporter/loadbalancingexporter/example/otel-agent-config.yaml
|
|
3
|
+
|
|
4
|
+
receivers:
|
|
5
|
+
fluentforward:
|
|
6
|
+
endpoint: 0.0.0.0:24224
|
|
7
|
+
|
|
8
|
+
processors:
|
|
9
|
+
batch:
|
|
10
|
+
|
|
11
|
+
exporters:
|
|
12
|
+
debug:
|
|
13
|
+
verbosity: detailed
|
|
14
|
+
loadbalancing:
|
|
15
|
+
protocol:
|
|
16
|
+
otlp:
|
|
17
|
+
timeout: 1s
|
|
18
|
+
tls:
|
|
19
|
+
insecure: true
|
|
20
|
+
resolver:
|
|
21
|
+
static:
|
|
22
|
+
hostnames:
|
|
23
|
+
- otel-collector-1:4317
|
|
24
|
+
- otel-collector-2:4317
|
|
25
|
+
- otel-collector-3:4317
|
|
26
|
+
|
|
27
|
+
extensions:
|
|
28
|
+
health_check:
|
|
29
|
+
pprof:
|
|
30
|
+
zpages:
|
|
31
|
+
|
|
32
|
+
service:
|
|
33
|
+
extensions: [pprof, zpages, health_check]
|
|
34
|
+
pipelines:
|
|
35
|
+
logs:
|
|
36
|
+
receivers: [fluentforward]
|
|
37
|
+
processors: [batch]
|
|
38
|
+
exporters: [loadbalancing, debug]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Vendored from opentelemetry-collector-contrib v0.130.0 (Apache-2.0), unchanged below this header:
|
|
2
|
+
# https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.130.0/exporter/loadbalancingexporter/example/otel-collector-config.yaml
|
|
3
|
+
|
|
4
|
+
receivers:
|
|
5
|
+
otlp:
|
|
6
|
+
protocols:
|
|
7
|
+
grpc:
|
|
8
|
+
|
|
9
|
+
processors:
|
|
10
|
+
batch:
|
|
11
|
+
|
|
12
|
+
exporters:
|
|
13
|
+
debug:
|
|
14
|
+
verbosity: detailed
|
|
15
|
+
|
|
16
|
+
extensions:
|
|
17
|
+
health_check:
|
|
18
|
+
pprof:
|
|
19
|
+
zpages:
|
|
20
|
+
|
|
21
|
+
service:
|
|
22
|
+
extensions: [pprof, zpages, health_check]
|
|
23
|
+
pipelines:
|
|
24
|
+
logs:
|
|
25
|
+
receivers: [otlp]
|
|
26
|
+
processors: [batch]
|
|
27
|
+
exporters: [debug]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Vendored from opentelemetry-collector-contrib v0.130.0 (Apache-2.0), unchanged below this header:
|
|
2
|
+
# https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.130.0/examples/logline-filtering/otel-col-config-filter-in-logs.yaml
|
|
3
|
+
|
|
4
|
+
receivers:
|
|
5
|
+
filelog:
|
|
6
|
+
include: [/var/log/busybox/simple.log]
|
|
7
|
+
operators:
|
|
8
|
+
- type: filter
|
|
9
|
+
expr: 'body not matches "^WARN:"'
|
|
10
|
+
|
|
11
|
+
service:
|
|
12
|
+
pipelines:
|
|
13
|
+
logs:
|
|
14
|
+
receivers: [filelog]
|
|
15
|
+
exporters: [otlp/custom]
|
|
16
|
+
processors: []
|
|
17
|
+
|
|
18
|
+
exporters:
|
|
19
|
+
otlp/custom:
|
|
20
|
+
endpoint: http://0.0.0.0:4242
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Vendored from opentelemetry-collector-contrib v0.130.0 (Apache-2.0), unchanged below this header:
|
|
2
|
+
# https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.130.0/examples/logline-filtering/otel-col-config-filter-out-logs.yaml
|
|
3
|
+
|
|
4
|
+
receivers:
|
|
5
|
+
filelog:
|
|
6
|
+
include: [/var/log/busybox/simple.log]
|
|
7
|
+
operators:
|
|
8
|
+
- type: filter
|
|
9
|
+
expr: 'body matches "^INFO:"'
|
|
10
|
+
|
|
11
|
+
service:
|
|
12
|
+
pipelines:
|
|
13
|
+
logs:
|
|
14
|
+
receivers: [filelog]
|
|
15
|
+
exporters: [otlp/custom]
|
|
16
|
+
processors: []
|
|
17
|
+
|
|
18
|
+
exporters:
|
|
19
|
+
otlp/custom:
|
|
20
|
+
endpoint: http://0.0.0.0:4242
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Vendored from opentelemetry-collector-contrib v0.130.0 (Apache-2.0), unchanged below this header:
|
|
2
|
+
# https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.130.0/examples/secure-tracing/otel-collector-config.yaml
|
|
3
|
+
|
|
4
|
+
receivers:
|
|
5
|
+
otlp:
|
|
6
|
+
protocols:
|
|
7
|
+
grpc:
|
|
8
|
+
endpoint: 0.0.0.0:55690
|
|
9
|
+
tls:
|
|
10
|
+
cert_file: /etc/otel-collector.crt
|
|
11
|
+
key_file: /etc/otel-collector.key
|
|
12
|
+
|
|
13
|
+
processors:
|
|
14
|
+
batch:
|
|
15
|
+
|
|
16
|
+
exporters:
|
|
17
|
+
debug:
|
|
18
|
+
verbosity: detailed
|
|
19
|
+
|
|
20
|
+
service:
|
|
21
|
+
pipelines:
|
|
22
|
+
traces:
|
|
23
|
+
receivers: [otlp]
|
|
24
|
+
processors: [batch]
|
|
25
|
+
exporters: [debug]
|
|
26
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Vendored from opentelemetry-collector-contrib v0.130.0 (Apache-2.0), unchanged below this header:
|
|
2
|
+
# https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.130.0/connector/servicegraphconnector/testdata/service-graph-connector-config.yaml
|
|
3
|
+
|
|
4
|
+
receivers:
|
|
5
|
+
nop:
|
|
6
|
+
|
|
7
|
+
exporters:
|
|
8
|
+
nop:
|
|
9
|
+
|
|
10
|
+
connectors:
|
|
11
|
+
servicegraph:
|
|
12
|
+
latency_histogram_buckets: [1,2,3,4,5]
|
|
13
|
+
dimensions:
|
|
14
|
+
- dimension-1
|
|
15
|
+
- dimension-2
|
|
16
|
+
store:
|
|
17
|
+
ttl: 1s
|
|
18
|
+
max_items: 10
|
|
19
|
+
database_name_attributes: [db.name]
|
|
20
|
+
|
|
21
|
+
service:
|
|
22
|
+
pipelines:
|
|
23
|
+
traces:
|
|
24
|
+
receivers: [nop]
|
|
25
|
+
exporters: [servicegraph]
|
|
26
|
+
metrics:
|
|
27
|
+
receivers: [servicegraph]
|
|
28
|
+
exporters: [nop]
|
|
@@ -25,25 +25,54 @@ export const literalCredentialRule: LintRule = {
|
|
|
25
25
|
const diagnostics: LintDiagnostic[] = [];
|
|
26
26
|
const source = context.sourceFile;
|
|
27
27
|
|
|
28
|
+
// `const x = { ... }` (or `[...]`, or a string) anywhere in the file, so a
|
|
29
|
+
// config value lifted out of the constructor into a named const, the way
|
|
30
|
+
// COR001 asks, is scanned where it is used.
|
|
31
|
+
const consts = new Map<string, ts.Expression>();
|
|
32
|
+
const collect = (node: ts.Node) => {
|
|
33
|
+
if (ts.isVariableDeclarationList(node) && node.flags & ts.NodeFlags.Const) {
|
|
34
|
+
for (const d of node.declarations) {
|
|
35
|
+
if (ts.isIdentifier(d.name) && d.initializer) consts.set(d.name.text, d.initializer);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
ts.forEachChild(node, collect);
|
|
39
|
+
};
|
|
40
|
+
collect(source);
|
|
41
|
+
|
|
42
|
+
const flag = (key: string, node: ts.Node) =>
|
|
43
|
+
diagnostics.push({
|
|
44
|
+
ruleId: "OTEL002",
|
|
45
|
+
severity: "error",
|
|
46
|
+
message: `\`${key}\` is a literal credential; write "\${env:NAME}" (or "\${file:/path}") and let the collector read it at start-up`,
|
|
47
|
+
file: context.filePath,
|
|
48
|
+
...position(source, node),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const scanned = new Set<ts.Node>();
|
|
52
|
+
const scanValue = (key: string | undefined, value: ts.Expression) => {
|
|
53
|
+
let init: ts.Expression = value;
|
|
54
|
+
if (ts.isIdentifier(init)) {
|
|
55
|
+
const resolved = consts.get(init.text);
|
|
56
|
+
if (!resolved) return;
|
|
57
|
+
init = resolved;
|
|
58
|
+
}
|
|
59
|
+
if (ts.isObjectLiteralExpression(init) || ts.isArrayLiteralExpression(init)) {
|
|
60
|
+
if (scanned.has(init)) return;
|
|
61
|
+
scanned.add(init);
|
|
62
|
+
if (ts.isObjectLiteralExpression(init)) scan(init);
|
|
63
|
+
else for (const el of init.elements) scanValue(undefined, el as ts.Expression);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!key || !SECRET_KEY.test(key) || /_file$/i.test(key)) return;
|
|
67
|
+
const text = literalText(init);
|
|
68
|
+
if (text === undefined || text === "" || text.includes("${")) return;
|
|
69
|
+
flag(key, value);
|
|
70
|
+
};
|
|
71
|
+
|
|
28
72
|
const scan = (obj: ts.ObjectLiteralExpression) => {
|
|
29
73
|
for (const prop of obj.properties) {
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
const init = prop.initializer;
|
|
33
|
-
if (ts.isObjectLiteralExpression(init)) {
|
|
34
|
-
scan(init);
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
if (!key || !SECRET_KEY.test(key) || /_file$/i.test(key)) continue;
|
|
38
|
-
const text = literalText(init);
|
|
39
|
-
if (text === undefined || text === "" || text.includes("${")) continue;
|
|
40
|
-
diagnostics.push({
|
|
41
|
-
ruleId: "OTEL002",
|
|
42
|
-
severity: "error",
|
|
43
|
-
message: `\`${key}\` is a literal credential; write "\${env:NAME}" (or "\${file:/path}") and let the collector read it at start-up`,
|
|
44
|
-
file: context.filePath,
|
|
45
|
-
...position(source, init),
|
|
46
|
-
});
|
|
74
|
+
if (ts.isShorthandPropertyAssignment(prop)) scanValue(prop.name.text, prop.name);
|
|
75
|
+
else if (ts.isPropertyAssignment(prop)) scanValue(propertyName(prop), prop.initializer);
|
|
47
76
|
}
|
|
48
77
|
};
|
|
49
78
|
|
|
@@ -67,4 +67,20 @@ describe("OTEL002 literal credential", () => {
|
|
|
67
67
|
);
|
|
68
68
|
expect(diags).toEqual([]);
|
|
69
69
|
});
|
|
70
|
+
|
|
71
|
+
test("follows config lifted into named consts, and looks inside lists", () => {
|
|
72
|
+
const diags = literalCredentialRule.check(
|
|
73
|
+
ctx(`
|
|
74
|
+
const headers: OtlpExporterConfig["headers"] = { authorization: "Bearer abc123" };
|
|
75
|
+
const safe = { authorization: "Bearer \${env:TOKEN}" };
|
|
76
|
+
const token = "literal";
|
|
77
|
+
const config = { scrape_configs: [{ job_name: "x", basic_auth: { username: "u", password: "p" } }] };
|
|
78
|
+
new OtlpExporter({ endpoint: "x:4317", headers });
|
|
79
|
+
new OtlpExporter({ name: "b", endpoint: "x:4317", headers: safe });
|
|
80
|
+
new SplunkHecExporter({ token, endpoint: "https://hec" });
|
|
81
|
+
new PrometheusReceiver({ config });
|
|
82
|
+
`),
|
|
83
|
+
);
|
|
84
|
+
expect(diags.map((d) => d.message.split("`")[1])).toEqual(["authorization", "token", "password"]);
|
|
85
|
+
});
|
|
70
86
|
});
|
package/src/plugin.ts
CHANGED
|
@@ -9,6 +9,9 @@ import { otelAuditCatalog } from "./lint/audit-catalog";
|
|
|
9
9
|
import { completions } from "./lsp/completions";
|
|
10
10
|
import { hover } from "./lsp/hover";
|
|
11
11
|
import { detectTemplate } from "./detect";
|
|
12
|
+
import { OtelCollectorParser } from "./import/parser";
|
|
13
|
+
import { OtelCollectorGenerator } from "./import/generator";
|
|
14
|
+
import { collectorConfigImporter } from "./import/embedded";
|
|
12
15
|
import { otelSkills } from "./skill-defs";
|
|
13
16
|
import { BUILTIN_CATALOG } from "./catalog";
|
|
14
17
|
import { COLLECTOR_PIN } from "./define";
|
|
@@ -96,6 +99,18 @@ export const otelPlugin: LexiconPlugin = {
|
|
|
96
99
|
return detectTemplate(data);
|
|
97
100
|
},
|
|
98
101
|
|
|
102
|
+
templateParser() {
|
|
103
|
+
return new OtelCollectorParser();
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
templateGenerator() {
|
|
107
|
+
return new OtelCollectorGenerator();
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
embeddedImporters() {
|
|
111
|
+
return [collectorConfigImporter];
|
|
112
|
+
},
|
|
113
|
+
|
|
99
114
|
completionProvider(ctx: CompletionContext) {
|
|
100
115
|
return completions(ctx);
|
|
101
116
|
},
|
package/src/skills/chant-otel.md
CHANGED
|
@@ -78,6 +78,17 @@ It deletes prompt, completion, system-instruction and tool-call content from spa
|
|
|
78
78
|
- Every pipeline needs at least one receiver and one exporter (OTEL102). A declared component no pipeline uses is a warning (OTEL103).
|
|
79
79
|
- Declared extensions are enabled in declaration order unless a `Service` lists `extensions` itself.
|
|
80
80
|
|
|
81
|
+
## Starting from an existing config
|
|
82
|
+
|
|
83
|
+
When the user already has a collector config file, import it rather than retyping it:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
chant import otel-collector-config.yaml --output src
|
|
87
|
+
chant build src --lexicon otel -o collector.yaml # the same config back
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The importer writes `receivers.ts`, `processors.ts`, `exporters.ts`, `connectors.ts`, `extensions.ts`, `pipelines.ts`, and `service.ts` when extensions or telemetry need a `Service`. A component type with no built-in class lands in `custom-components.ts` as a `defineComponent` whose config is untyped data; offer to give it a config interface. Settings outside a built-in's config type still import and build, but `tsc` flags them. Read the warnings `chant import` prints: they name anything the lexicon has no place for.
|
|
91
|
+
|
|
81
92
|
## Reading the result
|
|
82
93
|
|
|
83
94
|
`collectorTopologyOf(entities)` returns the pipelines, each component's endpoints and schema pin, for each exporter the signals it carries, the connector `edges` between pipelines, and under `semconv` the semantic-conventions version (`GENAI_SEMCONV_PIN`) the config's `gen_ai.` keys follow, as plain data.
|