@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,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixtures shared by the import round-trip tests (roundtrip.test.ts) and the
|
|
3
|
+
* type-check of the generated source (generated-types.e2e.test.ts).
|
|
4
|
+
*/
|
|
5
|
+
import { readdirSync, readFileSync, statSync } from "fs";
|
|
6
|
+
import { join, resolve } from "path";
|
|
7
|
+
import { build } from "@intentius/chant/build";
|
|
8
|
+
import type { SerializerResult } from "@intentius/chant/serializer";
|
|
9
|
+
import type { Declarable } from "@intentius/chant/declarable";
|
|
10
|
+
import { otelSerializer } from "../../serializer";
|
|
11
|
+
import { Pipeline, Service } from "../../pipeline";
|
|
12
|
+
import * as c from "../../components";
|
|
13
|
+
|
|
14
|
+
export const pkgDir = resolve(import.meta.dirname, "../../..");
|
|
15
|
+
export const repoRoot = resolve(pkgDir, "../..");
|
|
16
|
+
export const read = (...p: string[]) => readFileSync(join(import.meta.dirname, ...p), "utf-8");
|
|
17
|
+
|
|
18
|
+
export function primary(out: string | SerializerResult | undefined): string {
|
|
19
|
+
if (out === undefined) return "";
|
|
20
|
+
return typeof out === "string" ? out : out.primary;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Each otel example's `chant build` output. */
|
|
24
|
+
export async function exampleOutputs(): Promise<Array<[string, string]>> {
|
|
25
|
+
const examplesDir = join(pkgDir, "examples");
|
|
26
|
+
const out: Array<[string, string]> = [];
|
|
27
|
+
for (const name of readdirSync(examplesDir).sort()) {
|
|
28
|
+
const srcDir = join(examplesDir, name, "src");
|
|
29
|
+
try {
|
|
30
|
+
if (!statSync(srcDir).isDirectory()) continue;
|
|
31
|
+
} catch {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const result = await build(srcDir, [otelSerializer]);
|
|
35
|
+
if (result.errors.length > 0) throw new Error(`${name}: ${result.errors.map(String).join("; ")}`);
|
|
36
|
+
out.push([name, primary(result.outputs.get("otel"))]);
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const UPSTREAM_BUILTIN_ONLY = [
|
|
42
|
+
"kubernetes-filelog.yaml",
|
|
43
|
+
"logline-filter-in.yaml",
|
|
44
|
+
"logline-filter-out.yaml",
|
|
45
|
+
"secure-tracing.yaml",
|
|
46
|
+
"loadbalancing-backend.yaml",
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
/** One instance of every built-in, each using its typed fields, wired into pipelines the connectors accept. */
|
|
50
|
+
export function everyBuiltin(): Declarable[] {
|
|
51
|
+
const otlp = new c.OtlpReceiver({
|
|
52
|
+
protocols: {
|
|
53
|
+
grpc: { endpoint: "0.0.0.0:4317", max_recv_msg_size_mib: 16, keepalive: { server_parameters: { time: "30s" } } },
|
|
54
|
+
http: { endpoint: "0.0.0.0:4318", cors: { allowed_origins: ["https://*.example.com"] }, traces_url_path: "/v1/traces" },
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
const prometheusIn = new c.PrometheusReceiver({
|
|
58
|
+
name: "self",
|
|
59
|
+
config: {
|
|
60
|
+
global: { scrape_interval: "30s" },
|
|
61
|
+
scrape_configs: [{ job_name: "collector", scrape_interval: "10s", static_configs: [{ targets: ["localhost:8888"], labels: { tier: "gw" } }] }],
|
|
62
|
+
},
|
|
63
|
+
trim_metric_suffixes: true,
|
|
64
|
+
});
|
|
65
|
+
const hostmetrics = new c.HostMetricsReceiver({
|
|
66
|
+
collection_interval: "30s",
|
|
67
|
+
root_path: "/hostfs",
|
|
68
|
+
scrapers: { cpu: {}, memory: {}, filesystem: { exclude_mount_points: { match_type: "regexp", mount_points: ["/dev/.*"] } } },
|
|
69
|
+
});
|
|
70
|
+
const filelog = new c.FileLogReceiver({
|
|
71
|
+
include: ["/var/log/pods/*/*/*.log"],
|
|
72
|
+
exclude: ["/var/log/pods/*/otel-collector/*.log"],
|
|
73
|
+
start_at: "end",
|
|
74
|
+
include_file_path: true,
|
|
75
|
+
storage: "file_storage",
|
|
76
|
+
operators: [{ type: "container", id: "container-parser" }],
|
|
77
|
+
retry_on_failure: { enabled: true, initial_interval: "1s" },
|
|
78
|
+
});
|
|
79
|
+
const cluster = new c.K8sClusterReceiver({
|
|
80
|
+
auth_type: "serviceAccount",
|
|
81
|
+
collection_interval: "30s",
|
|
82
|
+
node_conditions_to_report: ["Ready", "MemoryPressure"],
|
|
83
|
+
allocatable_types_to_report: ["cpu", "memory"],
|
|
84
|
+
metrics: { "k8s.pod.phase": { enabled: false } },
|
|
85
|
+
});
|
|
86
|
+
const kubelet = new c.KubeletStatsReceiver({
|
|
87
|
+
auth_type: "serviceAccount",
|
|
88
|
+
endpoint: "https://${env:K8S_NODE_NAME}:10250",
|
|
89
|
+
insecure_skip_verify: true,
|
|
90
|
+
metric_groups: ["node", "pod", "container"],
|
|
91
|
+
extra_metadata_labels: ["container.id"],
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const batch = new c.BatchProcessor({ timeout: "5s", send_batch_size: 1024, send_batch_max_size: 2048, metadata_keys: ["tenant"] });
|
|
95
|
+
const memoryLimiter = new c.MemoryLimiterProcessor({ check_interval: "1s", limit_mib: 1024, spike_limit_mib: 256 });
|
|
96
|
+
const resource = new c.ResourceProcessor({
|
|
97
|
+
attributes: [
|
|
98
|
+
{ key: "deployment.environment", value: "${env:DEPLOY_ENV}", action: "upsert" },
|
|
99
|
+
{ key: "host.id", action: "delete" },
|
|
100
|
+
],
|
|
101
|
+
});
|
|
102
|
+
const attributes = new c.AttributesProcessor({
|
|
103
|
+
name: "scrub",
|
|
104
|
+
actions: [
|
|
105
|
+
{ key: "user.email", action: "hash" },
|
|
106
|
+
{ key: "http.status_code", action: "convert", converted_type: "int" },
|
|
107
|
+
],
|
|
108
|
+
include: { match_type: "strict", services: ["checkout"] },
|
|
109
|
+
});
|
|
110
|
+
const k8sattributes = new c.K8sAttributesProcessor({
|
|
111
|
+
auth_type: "serviceAccount",
|
|
112
|
+
passthrough: false,
|
|
113
|
+
filter: { node_from_env_var: "K8S_NODE_NAME" },
|
|
114
|
+
extract: { metadata: ["k8s.pod.name", "k8s.namespace.name"], labels: [{ tag_name: "app", key: "app.kubernetes.io/name", from: "pod" }] },
|
|
115
|
+
pod_association: [{ sources: [{ from: "resource_attribute", name: "k8s.pod.ip" }] }, { sources: [{ from: "connection" }] }],
|
|
116
|
+
});
|
|
117
|
+
const resourcedetection = new c.ResourceDetectionProcessor({
|
|
118
|
+
detectors: ["env", "system", "gcp"],
|
|
119
|
+
timeout: "2s",
|
|
120
|
+
override: false,
|
|
121
|
+
system: { hostname_sources: ["os"] },
|
|
122
|
+
});
|
|
123
|
+
const filter = new c.FilterProcessor({
|
|
124
|
+
name: "health",
|
|
125
|
+
error_mode: "ignore",
|
|
126
|
+
traces: { span: ['attributes["http.route"] == "/healthz"'] },
|
|
127
|
+
metrics: { datapoint: ['metric.name == "up" and value_int == 1'] },
|
|
128
|
+
logs: { log_record: ["severity_number < SEVERITY_NUMBER_INFO"] },
|
|
129
|
+
});
|
|
130
|
+
const transform = new c.TransformProcessor({
|
|
131
|
+
error_mode: "ignore",
|
|
132
|
+
trace_statements: [{ context: "span", conditions: ["kind == SPAN_KIND_SERVER"], statements: ['set(attributes["tier"], "edge")'] }],
|
|
133
|
+
metric_statements: ['delete_key(datapoint.attributes, "pod_ip")'],
|
|
134
|
+
log_statements: [{ context: "log", statements: ['set(severity_text, "WARN") where severity_number == 13'] }],
|
|
135
|
+
});
|
|
136
|
+
const redaction = new c.RedactionProcessor({
|
|
137
|
+
allow_all_keys: true,
|
|
138
|
+
blocked_key_patterns: ["^gen_ai\\.(prompt|completion)"],
|
|
139
|
+
blocked_values: ["4[0-9]{12}(?:[0-9]{3})?"],
|
|
140
|
+
hash_function: "sha3",
|
|
141
|
+
summary: "silent",
|
|
142
|
+
});
|
|
143
|
+
const tailSampling = new c.TailSamplingProcessor({
|
|
144
|
+
decision_wait: "10s",
|
|
145
|
+
num_traces: 50000,
|
|
146
|
+
sample_on_first_match: true,
|
|
147
|
+
policies: [
|
|
148
|
+
{ name: "errors", type: "status_code", status_code: { status_codes: ["ERROR"] } },
|
|
149
|
+
{ name: "slow", type: "latency", latency: { threshold_ms: 1000, upper_threshold_ms: 60000 } },
|
|
150
|
+
{ name: "vip", type: "boolean_attribute", boolean_attribute: { key: "vip", value: true } },
|
|
151
|
+
{ name: "sized", type: "span_count", span_count: { min_spans: 2, max_spans: 500 } },
|
|
152
|
+
{ name: "both", type: "and", and: { and_sub_policy: [{ name: "a", type: "rate_limiting", rate_limiting: { spans_per_second: 100 } }, { name: "b", type: "always_sample" }] } },
|
|
153
|
+
{ name: "rest", type: "probabilistic", probabilistic: { sampling_percentage: 5, hash_salt: "s" } },
|
|
154
|
+
],
|
|
155
|
+
});
|
|
156
|
+
const probabilistic = new c.ProbabilisticSamplerProcessor({ sampling_percentage: 12.5, mode: "proportional", sampling_precision: 4 });
|
|
157
|
+
|
|
158
|
+
const otlpOut = new c.OtlpExporter({
|
|
159
|
+
name: "backend",
|
|
160
|
+
endpoint: "backend:4317",
|
|
161
|
+
compression: "zstd",
|
|
162
|
+
headers: { "x-api-key": "${env:BACKEND_KEY}" },
|
|
163
|
+
tls: { insecure: false, ca_file: "/etc/ca.pem", min_version: "1.3" },
|
|
164
|
+
balancer_name: "round_robin",
|
|
165
|
+
timeout: "10s",
|
|
166
|
+
retry_on_failure: { enabled: true, max_elapsed_time: "2m" },
|
|
167
|
+
sending_queue: { enabled: true, num_consumers: 4, queue_size: 2000, sizer: "requests" },
|
|
168
|
+
});
|
|
169
|
+
const otlphttp = new c.OtlpHttpExporter({ endpoint: "https://otlp.example.com", encoding: "json", logs_endpoint: "https://logs.example.com/v1/logs" });
|
|
170
|
+
const debug = new c.DebugExporter({ verbosity: "detailed", sampling_initial: 5, sampling_thereafter: 200 });
|
|
171
|
+
const prometheusOut = new c.PrometheusExporter({
|
|
172
|
+
endpoint: "0.0.0.0:8889",
|
|
173
|
+
namespace: "otel",
|
|
174
|
+
const_labels: { cluster: "prod" },
|
|
175
|
+
metric_expiration: "5m",
|
|
176
|
+
resource_to_telemetry_conversion: { enabled: true },
|
|
177
|
+
});
|
|
178
|
+
const googlecloud = new c.GoogleCloudExporter({
|
|
179
|
+
project: "my-project",
|
|
180
|
+
metric: { prefix: "custom.googleapis.com", resource_filters: [{ prefix: "k8s." }] },
|
|
181
|
+
trace: { attribute_mappings: [{ key: "http.route", replacement: "/http/route" }] },
|
|
182
|
+
log: { default_log_name: "otel" },
|
|
183
|
+
});
|
|
184
|
+
const loadbalancing = new c.LoadBalancingExporter({
|
|
185
|
+
routing_key: "service",
|
|
186
|
+
protocol: { otlp: { timeout: "1s", tls: { insecure: true } } },
|
|
187
|
+
resolver: { k8s: { service: "sampling.observability", ports: [4317], return_hostnames: true } },
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const spanmetrics = new c.SpanMetricsConnector({
|
|
191
|
+
namespace: "span.metrics",
|
|
192
|
+
dimensions: [{ name: "http.route" }, { name: "env", default: "dev" }],
|
|
193
|
+
histogram: { unit: "s", exponential: { max_size: 160 } },
|
|
194
|
+
exemplars: { enabled: true, max_per_data_point: 5 },
|
|
195
|
+
metrics_flush_interval: "15s",
|
|
196
|
+
aggregation_temporality: "AGGREGATION_TEMPORALITY_DELTA",
|
|
197
|
+
});
|
|
198
|
+
const servicegraph = new c.ServiceGraphConnector({
|
|
199
|
+
latency_histogram_buckets: ["10ms", "100ms", "1s"],
|
|
200
|
+
dimensions: ["k8s.cluster.name"],
|
|
201
|
+
store: { ttl: "2s", max_items: 1000 },
|
|
202
|
+
virtual_node_peer_attributes: ["db.name"],
|
|
203
|
+
});
|
|
204
|
+
const routing = new c.RoutingConnector({
|
|
205
|
+
table: [{ context: "resource", condition: 'attributes["tenant"] == "acme"', pipelines: ["traces/acme"] }],
|
|
206
|
+
default_pipelines: ["traces/rest"],
|
|
207
|
+
error_mode: "ignore",
|
|
208
|
+
});
|
|
209
|
+
const forward = new c.ForwardConnector({});
|
|
210
|
+
const count = new c.CountConnector({
|
|
211
|
+
spans: { "span.count": { description: "Spans by service", attributes: [{ key: "service.name", default_value: "unknown" }] } },
|
|
212
|
+
});
|
|
213
|
+
const sum = new c.SumConnector({
|
|
214
|
+
spans: { "span.bytes": { source_attribute: "bytes", description: "Bytes by route", conditions: ['attributes["bytes"] != nil'] } },
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const health = new c.HealthCheckExtension({ endpoint: "0.0.0.0:13133", path: "/health", response_body: { healthy: "ok" } });
|
|
218
|
+
const pprof = new c.PprofExtension({ endpoint: "localhost:1777", block_profile_fraction: 3 });
|
|
219
|
+
const zpages = new c.ZPagesExtension({ endpoint: "localhost:55679" });
|
|
220
|
+
|
|
221
|
+
return [
|
|
222
|
+
otlp,
|
|
223
|
+
prometheusIn,
|
|
224
|
+
hostmetrics,
|
|
225
|
+
filelog,
|
|
226
|
+
cluster,
|
|
227
|
+
kubelet,
|
|
228
|
+
batch,
|
|
229
|
+
memoryLimiter,
|
|
230
|
+
resource,
|
|
231
|
+
attributes,
|
|
232
|
+
k8sattributes,
|
|
233
|
+
resourcedetection,
|
|
234
|
+
filter,
|
|
235
|
+
transform,
|
|
236
|
+
redaction,
|
|
237
|
+
tailSampling,
|
|
238
|
+
probabilistic,
|
|
239
|
+
otlpOut,
|
|
240
|
+
otlphttp,
|
|
241
|
+
debug,
|
|
242
|
+
prometheusOut,
|
|
243
|
+
googlecloud,
|
|
244
|
+
loadbalancing,
|
|
245
|
+
spanmetrics,
|
|
246
|
+
servicegraph,
|
|
247
|
+
routing,
|
|
248
|
+
forward,
|
|
249
|
+
count,
|
|
250
|
+
sum,
|
|
251
|
+
health,
|
|
252
|
+
pprof,
|
|
253
|
+
zpages,
|
|
254
|
+
new Pipeline({
|
|
255
|
+
signal: "traces",
|
|
256
|
+
receivers: [otlp],
|
|
257
|
+
processors: [memoryLimiter, k8sattributes, resourcedetection, resource, attributes, filter, transform, redaction, probabilistic],
|
|
258
|
+
exporters: [spanmetrics, servicegraph, count, sum, forward, routing, loadbalancing],
|
|
259
|
+
}),
|
|
260
|
+
new Pipeline({ signal: "traces", name: "acme", receivers: [routing], processors: [tailSampling, batch], exporters: [otlpOut] }),
|
|
261
|
+
new Pipeline({ signal: "traces", name: "rest", receivers: [routing, forward], processors: [batch], exporters: [googlecloud, debug] }),
|
|
262
|
+
new Pipeline({
|
|
263
|
+
signal: "metrics",
|
|
264
|
+
receivers: [otlp, prometheusIn, hostmetrics, cluster, kubelet, spanmetrics, servicegraph, count, sum],
|
|
265
|
+
processors: [memoryLimiter, filter, batch],
|
|
266
|
+
exporters: [prometheusOut, otlphttp],
|
|
267
|
+
}),
|
|
268
|
+
new Pipeline({ signal: "logs", receivers: [otlp, filelog], processors: [memoryLimiter, redaction, batch], exporters: [otlphttp, debug] }),
|
|
269
|
+
new Service({
|
|
270
|
+
extensions: [health, zpages, pprof],
|
|
271
|
+
telemetry: { logs: { level: "warn", encoding: "json" }, metrics: { level: "normal" }, resource: { "service.name": "gw" } },
|
|
272
|
+
}),
|
|
273
|
+
];
|
|
274
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# A two-tier trace gateway in one file. The front tier spreads spans across
|
|
2
|
+
# the sampling tier by trace id with the loadbalancing exporter; the sampling
|
|
3
|
+
# tier keeps whole traces with tail_sampling and derives RED metrics from
|
|
4
|
+
# every span with spanmetrics before sampling drops any.
|
|
5
|
+
|
|
6
|
+
receivers:
|
|
7
|
+
otlp:
|
|
8
|
+
protocols:
|
|
9
|
+
grpc:
|
|
10
|
+
endpoint: 0.0.0.0:4317
|
|
11
|
+
http:
|
|
12
|
+
endpoint: 0.0.0.0:4318
|
|
13
|
+
otlp/sampling:
|
|
14
|
+
protocols:
|
|
15
|
+
grpc:
|
|
16
|
+
endpoint: 0.0.0.0:14317
|
|
17
|
+
|
|
18
|
+
processors:
|
|
19
|
+
memory_limiter:
|
|
20
|
+
check_interval: 1s
|
|
21
|
+
limit_percentage: 75
|
|
22
|
+
spike_limit_percentage: 15
|
|
23
|
+
batch:
|
|
24
|
+
timeout: 5s
|
|
25
|
+
send_batch_size: 8192
|
|
26
|
+
tail_sampling:
|
|
27
|
+
decision_wait: 10s
|
|
28
|
+
num_traces: 100000
|
|
29
|
+
expected_new_traces_per_sec: 2000
|
|
30
|
+
decision_cache:
|
|
31
|
+
sampled_cache_size: 100000
|
|
32
|
+
policies:
|
|
33
|
+
- name: errors
|
|
34
|
+
type: status_code
|
|
35
|
+
status_code:
|
|
36
|
+
status_codes: [ERROR]
|
|
37
|
+
- name: slow
|
|
38
|
+
type: latency
|
|
39
|
+
latency:
|
|
40
|
+
threshold_ms: 1500
|
|
41
|
+
- name: checkout
|
|
42
|
+
type: string_attribute
|
|
43
|
+
string_attribute:
|
|
44
|
+
key: service.name
|
|
45
|
+
values: [checkout, payments]
|
|
46
|
+
- name: noisy-health
|
|
47
|
+
type: drop
|
|
48
|
+
drop:
|
|
49
|
+
drop_sub_policy:
|
|
50
|
+
- name: health-route
|
|
51
|
+
type: string_attribute
|
|
52
|
+
string_attribute:
|
|
53
|
+
key: http.route
|
|
54
|
+
values: [/healthz, /readyz]
|
|
55
|
+
- name: budget
|
|
56
|
+
type: composite
|
|
57
|
+
composite:
|
|
58
|
+
max_total_spans_per_second: 1000
|
|
59
|
+
policy_order: [errors-first, rest]
|
|
60
|
+
composite_sub_policy:
|
|
61
|
+
- name: errors-first
|
|
62
|
+
type: status_code
|
|
63
|
+
status_code:
|
|
64
|
+
status_codes: [ERROR]
|
|
65
|
+
- name: rest
|
|
66
|
+
type: always_sample
|
|
67
|
+
rate_allocation:
|
|
68
|
+
- policy: errors-first
|
|
69
|
+
percent: 60
|
|
70
|
+
- policy: rest
|
|
71
|
+
percent: 40
|
|
72
|
+
|
|
73
|
+
exporters:
|
|
74
|
+
loadbalancing:
|
|
75
|
+
routing_key: traceID
|
|
76
|
+
protocol:
|
|
77
|
+
otlp:
|
|
78
|
+
timeout: 2s
|
|
79
|
+
tls:
|
|
80
|
+
insecure: true
|
|
81
|
+
resolver:
|
|
82
|
+
dns:
|
|
83
|
+
hostname: otel-sampling-headless.observability.svc.cluster.local
|
|
84
|
+
port: "14317"
|
|
85
|
+
otlp/tempo:
|
|
86
|
+
endpoint: tempo.observability:4317
|
|
87
|
+
headers:
|
|
88
|
+
authorization: "Bearer ${env:TEMPO_TOKEN}"
|
|
89
|
+
tls:
|
|
90
|
+
insecure: false
|
|
91
|
+
ca_file: /etc/tls/ca.pem
|
|
92
|
+
sending_queue:
|
|
93
|
+
enabled: true
|
|
94
|
+
queue_size: 10000
|
|
95
|
+
retry_on_failure:
|
|
96
|
+
enabled: true
|
|
97
|
+
max_elapsed_time: 5m
|
|
98
|
+
prometheus:
|
|
99
|
+
endpoint: "0.0.0.0:8889"
|
|
100
|
+
namespace: gateway
|
|
101
|
+
resource_to_telemetry_conversion:
|
|
102
|
+
enabled: true
|
|
103
|
+
|
|
104
|
+
connectors:
|
|
105
|
+
spanmetrics:
|
|
106
|
+
namespace: traces.span.metrics
|
|
107
|
+
dimensions:
|
|
108
|
+
- name: http.route
|
|
109
|
+
- name: deployment.environment
|
|
110
|
+
default: "${env:DEPLOY_ENV}"
|
|
111
|
+
histogram:
|
|
112
|
+
explicit:
|
|
113
|
+
buckets: [10ms, 50ms, 100ms, 250ms, 1s, 5s]
|
|
114
|
+
exemplars:
|
|
115
|
+
enabled: true
|
|
116
|
+
metrics_flush_interval: 15s
|
|
117
|
+
|
|
118
|
+
extensions:
|
|
119
|
+
health_check:
|
|
120
|
+
endpoint: 0.0.0.0:13133
|
|
121
|
+
pprof:
|
|
122
|
+
endpoint: localhost:1777
|
|
123
|
+
zpages: {}
|
|
124
|
+
|
|
125
|
+
service:
|
|
126
|
+
extensions: [zpages, health_check]
|
|
127
|
+
telemetry:
|
|
128
|
+
logs:
|
|
129
|
+
level: info
|
|
130
|
+
encoding: json
|
|
131
|
+
metrics:
|
|
132
|
+
level: detailed
|
|
133
|
+
readers:
|
|
134
|
+
- pull:
|
|
135
|
+
exporter:
|
|
136
|
+
prometheus:
|
|
137
|
+
host: 0.0.0.0
|
|
138
|
+
port: 8888
|
|
139
|
+
resource:
|
|
140
|
+
service.name: otel-gateway
|
|
141
|
+
pipelines:
|
|
142
|
+
traces:
|
|
143
|
+
receivers: [otlp]
|
|
144
|
+
processors: [memory_limiter]
|
|
145
|
+
exporters: [loadbalancing]
|
|
146
|
+
traces/sampling:
|
|
147
|
+
receivers: [otlp/sampling]
|
|
148
|
+
processors: [memory_limiter, tail_sampling, batch]
|
|
149
|
+
exporters: [otlp/tempo, spanmetrics]
|
|
150
|
+
metrics/red:
|
|
151
|
+
receivers: [spanmetrics]
|
|
152
|
+
processors: [batch]
|
|
153
|
+
exporters: [prometheus]
|
|
@@ -0,0 +1,150 @@
|
|
|
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/couchbase/otel-collector-config.yaml
|
|
3
|
+
|
|
4
|
+
receivers:
|
|
5
|
+
prometheus/couchbase:
|
|
6
|
+
config:
|
|
7
|
+
scrape_configs:
|
|
8
|
+
- job_name: 'couchbase'
|
|
9
|
+
scrape_interval: 5s
|
|
10
|
+
static_configs:
|
|
11
|
+
- targets: ['couchbase:8091']
|
|
12
|
+
basic_auth:
|
|
13
|
+
username: 'otelu'
|
|
14
|
+
password: 'otelpassword'
|
|
15
|
+
metric_relabel_configs:
|
|
16
|
+
# Include only a few key metrics
|
|
17
|
+
- source_labels: [ __name__ ]
|
|
18
|
+
regex: "(kv_ops)|\
|
|
19
|
+
(kv_vb_curr_items)|\
|
|
20
|
+
(kv_num_vbuckets)|\
|
|
21
|
+
(kv_ep_cursor_memory_freed_bytes)|\
|
|
22
|
+
(kv_total_memory_used_bytes)|\
|
|
23
|
+
(kv_ep_num_value_ejects)|\
|
|
24
|
+
(kv_ep_mem_high_wat)|\
|
|
25
|
+
(kv_ep_mem_low_wat)|\
|
|
26
|
+
(kv_ep_tmp_oom_errors)|\
|
|
27
|
+
(kv_ep_oom_errors)"
|
|
28
|
+
action: keep
|
|
29
|
+
|
|
30
|
+
processors:
|
|
31
|
+
filter/couchbase:
|
|
32
|
+
# Filter out prometheus scraping meta-metrics.
|
|
33
|
+
metrics:
|
|
34
|
+
exclude:
|
|
35
|
+
match_type: strict
|
|
36
|
+
metric_names:
|
|
37
|
+
- scrape_samples_post_metric_relabeling
|
|
38
|
+
- scrape_series_added
|
|
39
|
+
- scrape_duration_seconds
|
|
40
|
+
- scrape_samples_scraped
|
|
41
|
+
- up
|
|
42
|
+
|
|
43
|
+
metricstransform/couchbase:
|
|
44
|
+
transforms:
|
|
45
|
+
# Rename from prometheus metric name to OTel metric name.
|
|
46
|
+
# We cannot do this with metric_relabel_configs, as the prometheus receiver does not
|
|
47
|
+
# allow metric renames at this time.
|
|
48
|
+
- include: kv_ops
|
|
49
|
+
match_type: strict
|
|
50
|
+
action: update
|
|
51
|
+
new_name: "couchbase.bucket.operation.count"
|
|
52
|
+
- include: kv_vb_curr_items
|
|
53
|
+
match_type: strict
|
|
54
|
+
action: update
|
|
55
|
+
new_name: "couchbase.bucket.item.count"
|
|
56
|
+
- include: kv_num_vbuckets
|
|
57
|
+
match_type: strict
|
|
58
|
+
action: update
|
|
59
|
+
new_name: "couchbase.bucket.vbucket.count"
|
|
60
|
+
- include: kv_ep_cursor_memory_freed_bytes
|
|
61
|
+
match_type: strict
|
|
62
|
+
action: update
|
|
63
|
+
new_name: "couchbase.bucket.memory.usage.free"
|
|
64
|
+
- include: kv_total_memory_used_bytes
|
|
65
|
+
match_type: strict
|
|
66
|
+
action: update
|
|
67
|
+
new_name: "couchbase.bucket.memory.usage.used"
|
|
68
|
+
- include: kv_ep_num_value_ejects
|
|
69
|
+
match_type: strict
|
|
70
|
+
action: update
|
|
71
|
+
new_name: "couchbase.bucket.item.ejection.count"
|
|
72
|
+
- include: kv_ep_mem_high_wat
|
|
73
|
+
match_type: strict
|
|
74
|
+
action: update
|
|
75
|
+
new_name: "couchbase.bucket.memory.high_water_mark.limit"
|
|
76
|
+
- include: kv_ep_mem_low_wat
|
|
77
|
+
match_type: strict
|
|
78
|
+
action: update
|
|
79
|
+
new_name: "couchbase.bucket.memory.low_water_mark.limit"
|
|
80
|
+
- include: kv_ep_tmp_oom_errors
|
|
81
|
+
match_type: strict
|
|
82
|
+
action: update
|
|
83
|
+
new_name: "couchbase.bucket.error.oom.count.recoverable"
|
|
84
|
+
- include: kv_ep_oom_errors
|
|
85
|
+
match_type: strict
|
|
86
|
+
action: update
|
|
87
|
+
new_name: "couchbase.bucket.error.oom.count.unrecoverable"
|
|
88
|
+
# Combine couchbase.bucket.error.oom.count.x and couchbase.bucket.memory.usage.x
|
|
89
|
+
# metrics.
|
|
90
|
+
- include: '^couchbase\.bucket\.error\.oom\.count\.(?P<error_type>unrecoverable|recoverable)$$'
|
|
91
|
+
match_type: regexp
|
|
92
|
+
action: combine
|
|
93
|
+
new_name: "couchbase.bucket.error.oom.count"
|
|
94
|
+
- include: '^couchbase\.bucket\.memory\.usage\.(?P<state>free|used)$$'
|
|
95
|
+
match_type: regexp
|
|
96
|
+
action: combine
|
|
97
|
+
new_name: "couchbase.bucket.memory.usage"
|
|
98
|
+
# Aggregate "result" label on operation count to keep label sets consistent across the metric datapoints
|
|
99
|
+
- include: 'couchbase.bucket.operation.count'
|
|
100
|
+
match_type: strict
|
|
101
|
+
action: update
|
|
102
|
+
operations:
|
|
103
|
+
- action: aggregate_labels
|
|
104
|
+
label_set: ["bucket", "op"]
|
|
105
|
+
aggregation_type: sum
|
|
106
|
+
|
|
107
|
+
transform/couchbase:
|
|
108
|
+
metric_statements:
|
|
109
|
+
- context: datapoint
|
|
110
|
+
statements:
|
|
111
|
+
- convert_gauge_to_sum("cumulative", true) where metric.name == "couchbase.bucket.operation.count"
|
|
112
|
+
- set(metric.description, "Number of operations on the bucket.") where metric.name == "couchbase.bucket.operation.count"
|
|
113
|
+
- set(metric.unit, "{operations}") where metric.name == "couchbase.bucket.operation.count"
|
|
114
|
+
|
|
115
|
+
- convert_gauge_to_sum("cumulative", false) where metric.name == "couchbase.bucket.item.count"
|
|
116
|
+
- set(metric.description, "Number of items that belong to the bucket.") where metric.name == "couchbase.bucket.item.count"
|
|
117
|
+
- set(metric.unit, "{items}") where metric.name == "couchbase.bucket.item.count"
|
|
118
|
+
|
|
119
|
+
- convert_gauge_to_sum("cumulative", false) where metric.name == "couchbase.bucket.vbucket.count"
|
|
120
|
+
- set(metric.description, "Number of non-resident vBuckets.") where metric.name == "couchbase.bucket.vbucket.count"
|
|
121
|
+
- set(metric.unit, "{vbuckets}") where metric.name == "couchbase.bucket.vbucket.count"
|
|
122
|
+
|
|
123
|
+
- convert_gauge_to_sum("cumulative", false) where metric.name == "couchbase.bucket.memory.usage"
|
|
124
|
+
- set(metric.description, "Usage of total memory available to the bucket.") where metric.name == "couchbase.bucket.memory.usage"
|
|
125
|
+
- set(metric.unit, "By") where metric.name == "couchbase.bucket.memory.usage"
|
|
126
|
+
|
|
127
|
+
- convert_gauge_to_sum("cumulative", true) where metric.name == "couchbase.bucket.item.ejection.count"
|
|
128
|
+
- set(metric.description, "Number of item value ejections from memory to disk.") where metric.name == "couchbase.bucket.item.ejection.count"
|
|
129
|
+
- set(metric.unit, "{ejections}") where metric.name == "couchbase.bucket.item.ejection.count"
|
|
130
|
+
|
|
131
|
+
- convert_gauge_to_sum("cumulative", true) where metric.name == "couchbase.bucket.error.oom.count"
|
|
132
|
+
- set(metric.description, "Number of out of memory errors.") where metric.name == "couchbase.bucket.error.oom.count"
|
|
133
|
+
- set(metric.unit, "{errors}") where metric.name == "couchbase.bucket.error.oom.count"
|
|
134
|
+
|
|
135
|
+
- set(metric.description, "The memory usage at which items will be ejected.") where metric.name == "couchbase.bucket.memory.high_water_mark.limit"
|
|
136
|
+
- set(metric.unit, "By") where metric.name == "couchbase.bucket.memory.high_water_mark.limit"
|
|
137
|
+
|
|
138
|
+
- set(metric.description, "The memory usage at which ejections will stop that were previously triggered by a high water mark breach.") where metric.name == "couchbase.bucket.memory.low_water_mark.limit"
|
|
139
|
+
- set(metric.unit, "By") where metric.name == "couchbase.bucket.memory.low_water_mark.limit"
|
|
140
|
+
|
|
141
|
+
exporters:
|
|
142
|
+
prometheus:
|
|
143
|
+
endpoint: "0.0.0.0:9123"
|
|
144
|
+
|
|
145
|
+
service:
|
|
146
|
+
pipelines:
|
|
147
|
+
metrics/couchbase:
|
|
148
|
+
receivers: [prometheus/couchbase]
|
|
149
|
+
processors: [filter/couchbase, metricstransform/couchbase, transform/couchbase]
|
|
150
|
+
exporters: [prometheus]
|
|
@@ -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/examples/fault-tolerant-logs-collection/otel-col-config.yaml
|
|
3
|
+
|
|
4
|
+
receivers:
|
|
5
|
+
filelog:
|
|
6
|
+
include: [/var/log/busybox/simple.log]
|
|
7
|
+
storage: file_storage/filelogreceiver
|
|
8
|
+
|
|
9
|
+
extensions:
|
|
10
|
+
file_storage/filelogreceiver:
|
|
11
|
+
directory: /var/lib/otelcol/file_storage/receiver
|
|
12
|
+
file_storage/otlpoutput:
|
|
13
|
+
directory: /var/lib/otelcol/file_storage/output
|
|
14
|
+
|
|
15
|
+
service:
|
|
16
|
+
extensions: [file_storage/filelogreceiver, file_storage/otlpoutput]
|
|
17
|
+
pipelines:
|
|
18
|
+
logs:
|
|
19
|
+
receivers: [filelog]
|
|
20
|
+
exporters: [otlp/custom]
|
|
21
|
+
processors: []
|
|
22
|
+
|
|
23
|
+
exporters:
|
|
24
|
+
otlp/custom:
|
|
25
|
+
endpoint: http://0.0.0.0:4242
|
|
26
|
+
sending_queue:
|
|
27
|
+
storage: file_storage/otlpoutput
|
|
@@ -0,0 +1,86 @@
|
|
|
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/kubernetes/otel-collector-config.yml
|
|
3
|
+
|
|
4
|
+
receivers:
|
|
5
|
+
filelog:
|
|
6
|
+
include:
|
|
7
|
+
- /var/log/pods/*/*/*.log
|
|
8
|
+
exclude:
|
|
9
|
+
# Exclude logs from all containers named otel-collector
|
|
10
|
+
- /var/log/pods/*/otel-collector/*.log
|
|
11
|
+
start_at: end
|
|
12
|
+
include_file_path: true
|
|
13
|
+
include_file_name: false
|
|
14
|
+
operators:
|
|
15
|
+
# Find out which format is used by kubernetes
|
|
16
|
+
- type: router
|
|
17
|
+
id: get-format
|
|
18
|
+
routes:
|
|
19
|
+
- output: parser-docker
|
|
20
|
+
expr: 'body matches "^\\{"'
|
|
21
|
+
- output: parser-crio
|
|
22
|
+
expr: 'body matches "^[^ Z]+ "'
|
|
23
|
+
- output: parser-containerd
|
|
24
|
+
expr: 'body matches "^[^ Z]+Z"'
|
|
25
|
+
# Parse CRI-O format
|
|
26
|
+
- type: regex_parser
|
|
27
|
+
id: parser-crio
|
|
28
|
+
regex: '^(?P<time>[^ Z]+) (?P<stream>stdout|stderr) (?P<logtag>[^ ]*) ?(?P<log>.*)$'
|
|
29
|
+
output: extract_metadata_from_filepath
|
|
30
|
+
timestamp:
|
|
31
|
+
parse_from: attributes.time
|
|
32
|
+
layout_type: gotime
|
|
33
|
+
layout: '2006-01-02T15:04:05.999999999Z07:00'
|
|
34
|
+
# Parse CRI-Containerd format
|
|
35
|
+
- type: regex_parser
|
|
36
|
+
id: parser-containerd
|
|
37
|
+
regex: '^(?P<time>[^ ^Z]+Z) (?P<stream>stdout|stderr) (?P<logtag>[^ ]*) ?(?P<log>.*)$'
|
|
38
|
+
output: extract_metadata_from_filepath
|
|
39
|
+
timestamp:
|
|
40
|
+
parse_from: attributes.time
|
|
41
|
+
layout: '%Y-%m-%dT%H:%M:%S.%LZ'
|
|
42
|
+
# Parse Docker format
|
|
43
|
+
- type: json_parser
|
|
44
|
+
id: parser-docker
|
|
45
|
+
output: extract_metadata_from_filepath
|
|
46
|
+
timestamp:
|
|
47
|
+
parse_from: attributes.time
|
|
48
|
+
layout: '%Y-%m-%dT%H:%M:%S.%LZ'
|
|
49
|
+
# Extract metadata from file path
|
|
50
|
+
- type: regex_parser
|
|
51
|
+
id: extract_metadata_from_filepath
|
|
52
|
+
regex: '^.*\/(?P<namespace>[^_]+)_(?P<pod_name>[^_]+)_(?P<uid>[a-f0-9\-]{36})\/(?P<container_name>[^\._]+)\/(?P<restart_count>\d+)\.log$'
|
|
53
|
+
parse_from: attributes["log.file.path"]
|
|
54
|
+
cache:
|
|
55
|
+
size: 128 # default maximum amount of Pods per Node is 110
|
|
56
|
+
# Update body field after finishing all parsing
|
|
57
|
+
- type: move
|
|
58
|
+
from: attributes.log
|
|
59
|
+
to: body
|
|
60
|
+
# Rename attributes
|
|
61
|
+
- type: move
|
|
62
|
+
from: attributes.stream
|
|
63
|
+
to: attributes["log.iostream"]
|
|
64
|
+
- type: move
|
|
65
|
+
from: attributes.container_name
|
|
66
|
+
to: resource["k8s.container.name"]
|
|
67
|
+
- type: move
|
|
68
|
+
from: attributes.namespace
|
|
69
|
+
to: resource["k8s.namespace.name"]
|
|
70
|
+
- type: move
|
|
71
|
+
from: attributes.pod_name
|
|
72
|
+
to: resource["k8s.pod.name"]
|
|
73
|
+
- type: move
|
|
74
|
+
from: attributes.restart_count
|
|
75
|
+
to: resource["k8s.container.restart_count"]
|
|
76
|
+
- type: move
|
|
77
|
+
from: attributes.uid
|
|
78
|
+
to: resource["k8s.pod.uid"]
|
|
79
|
+
exporters:
|
|
80
|
+
debug:
|
|
81
|
+
verbosity: detailed
|
|
82
|
+
service:
|
|
83
|
+
pipelines:
|
|
84
|
+
logs:
|
|
85
|
+
receivers: [filelog]
|
|
86
|
+
exporters: [debug]
|