Repository navigation
Expand file tree
/
Copy pathtelemetryd.toml.example
More file actions
163 lines (147 loc) · 7.74 KB
/
Copy pathtelemetryd.toml.example
File metadata and controls
163 lines (147 loc) · 7.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# telemetryd configuration — every value below is the default.
#
# You do not need this file. `telemetryd serve` with no configuration at all is a
# complete, supported setup; this exists only to override parts of it. Copy it to
# ./telemetryd.toml (or /etc/telemetryd/telemetryd.toml) and delete everything you
# are not changing — partial files are the normal case.
#
# Every scalar is also settable as TELEMETRYD_<SECTION>_<KEY>, e.g.
# TELEMETRYD_STORAGE_DATA_DIR. Precedence: defaults → this file → env → CLI flags.
#
# Check what actually takes effect with: telemetryd validate
[server]
listen = "127.0.0.1:4319" # one port: ingest + query + UI APIs
# grpc_listen = "127.0.0.1:4317" # OTLP/gRPC ingest, off unless set
insecure = false # allow a non-loopback bind with no token — see [auth]
max_body_bytes = "16MiB" # applies to the decompressed body too
request_timeout = "30s"
shutdown_grace = "15s"
[auth]
# Both accept a string or a list. A list lets you rotate with no rejection window.
# Indirection avoids putting a secret in a world-readable file:
# ingest_token = "file:/run/secrets/ingest"
# query_token = "env:TELEMETRYD_QUERY_SECRET"
#
# Empty means that surface is unauthenticated. That is fine on loopback; binding a
# non-loopback address with both empty is refused at startup (see ADR-004).
ingest_token = [] # /v1/*, /api/v1/write
query_token = [] # Loki/Tempo/Prometheus reads, /status, /metrics
# Guards /status and /metrics, which describe the deployment rather than the
# telemetry: app names, per-app series and disk share, whether this instance is
# running unauthenticated. Unset means query_token guards them, as it always did.
# admin_token = "..."
# Accept Cbox ID access tokens alongside the static ones. Tokens are validated
# locally against the issuer's published keys — telemetryd never asks the provider
# about a token, so an identity provider that is down does not stop you reading your
# logs. Unset means static tokens only.
# [auth.oidc]
# issuer = "https://acme.cboxid.com"
# audience = "https://telemetry.example.com" # when several services share an issuer
# scope_read = "telemetry:read"
#
# Any OIDC provider works, not only Cbox ID — but two things are not universal, so
# they are settings rather than assumptions:
# jwks_url = "" # "" derives {issuer}/.well-known/jwks.json; set it when the
# # provider publishes elsewhere (its discovery document's
# # `jwks_uri` says where)
# scope_claim = "scope" # the claim carrying granted scopes; some providers use "scp"
# Stand in front of a central instance and decide who each client is from its
# credential rather than from its payload. For mobile fleets, where the credential
# lives in a binary anyone can open. See docs/cookbook/relay-mode.md.
# [relay]
# upstream = "https://telemetry.internal"
# token = "file:/run/secrets/upstream"
#
# [[relay.client]]
# app = "mobile-ios"
# token = "file:/run/secrets/mobile-ios"
# Terminate TLS here instead of at a proxy. For internal deployments with nowhere to
# put one; bring a certificate your clients already trust rather than a self-signed one.
# [server.tls]
# cert_file = "/etc/telemetryd/tls/server.pem"
# key_file = "/etc/telemetryd/tls/server.key"
#
# Or, with no CA to hand: generate one for these names into <data_dir>/tls on first
# start. Encrypts, but cannot prove identity — clients must skip verification, and that
# setting outlives the certificate. Good against passive capture; not the destination.
# self_signed = "telemetry.internal"
# Trust for connections telemetryd makes — the OIDC key fetch, relay shipping,
# transfer. Set it when the issuer or the upstream is behind an internal authority;
# it replaces the built-in roots rather than adding to them.
# [tls]
# ca_file = "/etc/ssl/certs/internal-ca.pem"
[storage]
# Empty = automatic: ./telemetryd-data if it already exists, else the platform data
# directory. The resolved path is logged at startup and shown in /status.
data_dir = ""
disk_budget = "10GiB" # hard cap across all signals; the reaper enforces it
segment_duration = "1h"
max_segment_bytes = "256MiB" # seal early on size, so memory is bounded under a burst
# always — fsync every batch; safest, and caps ingest at the device's sync rate
# interval — fsync on a timer; you can lose up to wal_sync_interval on power loss
# never — test and benchmark use only
wal_sync = "interval"
wal_sync_interval = "100ms"
compression = "zstd" # zstd | snappy | none
# Threads one query may use to scan sealed segments. Off by default: once the
# allocator stopped being the bottleneck, four workers were worth about 7% on an
# unbounded scan and nothing on a limited one. 0 picks a fraction of the machine.
#
# Only unbounded queries ever use more than one thread. A query with a limit is fast
# because the collector's cutoff lets it skip whole segments unopened, and workers
# racing ahead just redo work that would have been skipped — measured 60% slower.
query_parallelism = 1
[retention]
# Metrics are kept longer because they are ~100x cheaper per unit time, and
# week-over-week comparison is most of what dashboards are for. disk_budget is still
# the hard cap over all signals.
logs = "7d"
traces = "7d"
metrics = "30d"
[limits]
# Exceeding any of these rejects the record loudly: a labelled counter on
# telemetryd_ingest_rejected_total, a structured error, and a count in /status.
# Nothing here causes a silent drop.
# Distinct *active* series. 0 derives it from the memory this process may use,
# at a measured ~1.0 KB per series. A series that goes quiet gives its slot back.
max_series = 0
# Fairness between apps, not a memory ceiling. 0 means "same as max_series", so it
# does not bind; lower it when several apps share an instance.
max_series_per_app = 0
# The most samples ONE PromQL query may load. 0 derives it from the memory limit.
# PromQL has no `limit`, and a query reads its whole window in one pass, so this is
# the only ceiling on what one chart can cost.
max_query_samples = 0
# Silence after which a series gives its slot back. 0 turns reclaiming off.
series_idle_after = "1h"
# refuse | evict_oldest — when the budget is full of series that are ALL still
# active. refuse keeps the admitted set complete and says so loudly; evict_oldest
# makes it a ring buffer, so nothing is turned away but busy series get holes.
when_series_full = "refuse"
max_labels_per_series = 60
max_label_name_bytes = 128
max_label_value_bytes = 2048
max_log_line_bytes = "256KiB"
max_attrs_per_record = 128
ingest_queue_depth = 8192 # full queue → 429 with Retry-After, not unbounded buffering
ingest_memory = 0 # memory ingest in flight may hold; 0 = a quarter of the limit
[ingest]
# Which resource attributes become *stream* labels, on top of `app` and `level`
# which are always present. This list is the cardinality contract: attributes not
# listed here are still stored and still queryable through label filters, they just
# do not create a new stream. Promoting something per-process or per-deploy here
# (host.id, process.pid, container.id) is how a log store dies of cardinality.
stream_labels = [
"service_name",
"service_namespace",
"service_version",
"deployment_environment",
"deployment_environment_name",
]
# Truncate an over-long body rather than rejecting the record outright. A giant
# stack trace is usually the most interesting line of the day. Truncation is marked
# in the body and counted, never invisible.
truncate_oversized_bodies = true
[log]
level = "info" # RUST_LOG overrides this when set
format = "text" # text | json