ЁЯФн рдзрдбрд╛ 06 тАФ OpenTelemetry: рд╕рдЧрд│реЗ рдЧреЛрд│рд╛ рдХрд░рдгреНрдпрд╛рдЪрд╛ рдПрдХрдЪ рдорд╛рд░реНрдЧ
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 06 ┬╖ рдорд╛рдЧреЗ: lesson-05-tracing ┬╖ рдкреБрдвреЗ: lesson-07-prometheus-grafana
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ05, рдЖрдгрд┐ рддрд┐рдиреНрд╣реА signals рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪреА рдЖрдгрд┐ рдкреБрдвреЗ рдиреЗрдгреНрдпрд╛рдЪреА standard рдкрджреНрдзрдд:
OpenTelemetry (OTel). рддреБрдореНрд╣реА API рдЖрдгрд┐ SDK, OTLP protocol,
Collector (receivers тЖТ processors тЖТ exporters), head рд╡рд┐рд░реБрджреНрдз tail sampling, рдЖрдгрд┐
semantic conventions рд╢рд┐рдХрддрд╛. obs/signals.py рдордзреАрд▓ Collector class
tail sampling рдЪреЗ model рдЖрд╣реЗ; obs/demo.py рдордзреАрд▓ otel() 1,000 traces
рддреНрдпрд╛рдордзреВрди рдЪрд╛рд▓рд╡рддреЗ.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рдкреВрд░реНрд╡реА рд╢рд╛рд│реЗрддрд▓реА рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрд▓реА рдЖрдкрд╛рдкрд▓реНрдпрд╛ рдкрджреНрдзрддреАрдиреЗ рдиреЛрдВрджреА рдареЗрд╡рд╛рдпрдЪреА. Office рдкреЗрдиреНрд╕рд┐рд▓рдиреЗ рд▓рд┐рд╣рд╛рдпрдЪреЗ, рдЧреНрд░рдВрдерд╛рд▓рдп cards рд╡рд╛рдкрд░рд╛рдпрдЪреЗ, рд╢рд┐рдХреНрд╖рдХ рдХрдХреНрд╖ whiteboard рд╡рд╛рдкрд░рд╛рдпрдЪрд╛. рдХрддрд░рд┐рдирд╛рд▓рд╛ рддреНрдпрд╛рдВрдЪреА рдмреЗрд░реАрдЬ рдХрд░рддрд╛ рдпреЗрдд рдирд╡реНрд╣рддреА.
рдореНрд╣рдгреВрди рджреАрдкрд┐рдХрд╛ рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрд▓реАрд▓рд╛ рдПрдХрдЪ form ЁЯУЛ рджреЗрддреЗ, рддреНрдпрд╛рдЪ рдЪреМрдХрдЯреА рдЖрдгрд┐ рддреЗрдЪ рд╢рдмреНрдж рдЕрд╕рд▓реЗрд▓рд╛: "рд╡рд░реНрдЧ", "рдЖрдд рдпреЗрдгреНрдпрд╛рдЪреА рд╡реЗрд│", "рдХрд╛рдп рдШрдбрд▓реЗ". рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрд▓реА рдЖрдкрд▓реЗ forms рд╡реНрд╣рд░рд╛рдВрдбреНрдпрд╛рддрд▓реНрдпрд╛ рдПрдХрд╛рдЪ рдкрддреНрд░рдкреЗрдЯреАрдд ЁЯУо рдЯрд╛рдХрддреЗ. рдПрдХ рдорджрддрдиреАрд╕ рдкрддреНрд░рдкреЗрдЯреА рд░рд┐рдХрд╛рдореА рдХрд░рддреЗ: рддреА forms рдЪреЗ рдЧрдареНрдареЗ рдмрд╛рдВрдзрддреЗ, рдмрд╣реБрддреЗрдХ рдХрдВрдЯрд╛рд│рд╡рд╛рдгреЗ forms рдЯрд╛рдХреВрди рджреЗрддреЗ ("рд╡рд┐рджреНрдпрд╛рд░реНрдереА рдареАрдХ, 2 рдорд┐рдирд┐рдЯреЗ"), рдЖрдЬрд╛рд░реА рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдХрд┐рдВрд╡рд╛ рдЦреВрдк рд╡реЗрд│ рд╡рд╛рдЯ рдкрд╛рд╣рд┐рд▓реЗрд▓реНрдпрд╛ рд╡рд┐рджреНрдпрд╛рд░реНрдереНрдпрд╛рдмрджреНрджрд▓рдЪрд╛ рдкреНрд░рддреНрдпреЗрдХ form рдареЗрд╡рддреЗ, рдЖрдгрд┐ рдЧрдареНрдард╛ рдЬрд┐рдереЗ рдЧрд░рдЬ рдЖрд╣реЗ рддрд┐рдереЗ рдкрд╛рдард╡рддреЗ тАФ рдЖрд░реЛрдЧреНрдп рдХрдХреНрд╖, рдореБрдЦреНрдпрд╛рдзреНрдпрд╛рдкрд┐рдХреЗрдЪреЗ office, рдХрд┐рдВрд╡рд╛ рджреЛрдиреНрд╣реАрдХрдбреЗ.
рддреЛрдЪ рдПрдХ form рдореНрд╣рдгрдЬреЗ semantic conventions. рдкрддреНрд░рдкреЗрдЯреА рдЖрдгрд┐ рдорджрддрдиреАрд╕ рдореНрд╣рдгрдЬреЗ Collector. Forms рд╡рд╛рдЪрд▓реНрдпрд╛рдирдВрддрд░ рд░реЛрдЪрдХ forms рдареЗрд╡рдгреЗ рдореНрд╣рдгрдЬреЗ tail sampling.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
subgraph app["ЁЯН│ results-api"]
api["OTel API<br/>(your code calls this)"] --> sdk["OTel SDK<br/>resource: service.name<br/>batch + export"]
end
sdk -->|"OTLP<br/>gRPC 4317 ┬╖ HTTP 4318"| rx
subgraph col["ЁЯУо OpenTelemetry Collector"]
rx["receivers<br/>otlp, prometheus"] --> pr["processors<br/>memory_limiter тЖТ tail_sampling тЖТ batch"] --> exp["exporters<br/>otlp, prometheusremotewrite"]
end
exp --> t["ЁЯЧ║я╕П Tempo / Jaeger / X-Ray"]
exp --> m["ЁЯУК Prometheus / Mimir"]
exp --> dd["ЁЯР╢ Datadog"]
s["1,000 traces тЖТ keep 113<br/>all 4 errors ┬╖ all 10 slow ┬╖ 1 in 10 of the rest"]
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/observability/lesson-diagrams.html#l06
тЭУ рдХрд╛рдп
- OpenTelemetry (OTel) тАФ traces, metrics рдЖрдгрд┐ logs рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ рдкреБрдвреЗ рдиреЗрдгреНрдпрд╛рд╕рд╛рдареА рдПрдХ open-source, рдХреЛрдгрддреНрдпрд╛рд╣реА vendor рд▓рд╛ рди рдмрд╛рдВрдзрд▓реЗрд▓реЗ standard (рдПрдХ CNCF project). рддреБрдореНрд╣реА рдПрдХрджрд╛рдЪ instrument рдХрд░рддрд╛; backend рд╣рд╛ рдлрдХреНрдд configuration рдЪрд╛ рдирд┐рд░реНрдгрдп рдЕрд╕рддреЛ.
- API тАФ рддреБрдордЪрд╛ code рдЖрдгрд┐ libraries рдЬреНрдпрд╛рдВрдирд╛ call рдХрд░рддрд╛рдд рддреА interfaces (
tracer.start_as_current_span,meter.create_counter). SDK install рдирд╕реЗрд▓ рддрд░ API рдХрд╛рд╣реАрдЪ рдХрд░рдд рдирд╛рд╣реА тАФ рдореНрд╣рдгреВрди libraries рддреЗ рд╕реБрд░рдХреНрд╖рд┐рддрдкрдгреЗ рд╕рдорд╛рд╡рд┐рд╖реНрдЯ рдХрд░реВ рд╢рдХрддрд╛рдд. - SDK тАФ рддреБрдордЪреНрдпрд╛ process рдордзрд▓реА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА: рддреЗ spans рдЖрдгрд┐ metric points рдмрдирд╡рддреЗ,
sampling рд▓рд╛рдЧреВ рдХрд░рддреЗ, resource рдЬреЛрдбрддреЗ (рдХреЛрдг рдкрд╛рдард╡рдд рдЖрд╣реЗ:
service.name,service.version,deployment.environment), batch рдХрд░рддреЗ рдЖрдгрд┐ export рдХрд░рддреЗ. - Auto-instrumentation тАФ рдиреЗрд╣рдореАрдЪреНрдпрд╛ frameworks рдЖрдгрд┐ clients рд╕рд╛рдареА рддрдпрд╛рд░ instrumentation (HTTP servers, HTTP clients, database drivers), рд╕рд╣рд╕рд╛ code рди рдмрджрд▓рддрд╛ рдЪрд╛рд▓реВ рдХрд░рддрд╛ рдпреЗрддреЗ.
- OTLP тАФ OpenTelemetry Protocol, SDKs, Collectors рдЖрдгрд┐ backends рдпрд╛рдВрдЪреНрдпрд╛рддрд▓рд╛ wire format. Default ports: 4317 (gRPC) рдЖрдгрд┐ 4318 (HTTP).
- Collector тАФ telemetry рдШреЗрдгрд╛рд░реА, рддреНрдпрд╛рд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдгрд╛рд░реА рдЖрдгрд┐ export рдХрд░рдгрд╛рд░реА рдПрдХ рд╡реЗрдЧрд│реА process. рддреА
pipelines рдкрд╛рд╕реВрди рдмрдирд▓реЗрд▓реА рдЕрд╕рддреЗ (рдкреНрд░рддреНрдпреЗрдХ signal рд╕рд╛рдареА рдПрдХ: traces, metrics, logs), рдкреНрд░рддреНрдпреЗрдХрд╛рдд:
- receivers тАФ data рдЖрдд рдХрд╕рд╛ рдпреЗрддреЛ (
otlp,prometheus,filelogтАж); - processors тАФ рддреНрдпрд╛рдЪреЗ рдХрд╛рдп рд╣реЛрддреЗ (
memory_limiter,batch, fields рдЬреЛрдбрдгреНрдпрд╛рд╕рд╛рдареА рдХрд┐рдВрд╡рд╛ рдХрд╛рдврдгреНрдпрд╛рд╕рд╛рдареАattributes,tail_samplingтАж); - exporters тАФ рддреЛ рдХреБрдареЗ рдЬрд╛рддреЛ (
otlp,otlphttp,prometheusremotewrite, vendor exporters). рддреА agent рдореНрд╣рдгреВрди (рдкреНрд░рддреНрдпреЗрдХ app рдХрд┐рдВрд╡рд╛ node рд╢реЗрдЬрд╛рд░реА) рдЖрдгрд┐/рдХрд┐рдВрд╡рд╛ gateway рдореНрд╣рдгреВрди (рдПрдХ рдордзреНрдпрд╡рд░реНрддреА pool) рдЪрд╛рд▓рддреЗ.
- receivers тАФ data рдЖрдд рдХрд╕рд╛ рдпреЗрддреЛ (
- Head sampling тАФ trace record рдХрд░рд╛рдпрдЪрд╛ рдХреА рдирд╛рд╣реА рд╣реЗ рд╕реБрд░реБрд╡рд╛рддреАрд▓рд╛рдЪ, рдкрд╣рд┐рд▓реНрдпрд╛
service рдордзреНрдпреЗ рдард░рд╡рдгреЗ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде "trace id рдиреБрд╕рд╛рд░ 10% рдареЗрд╡рд╛"); рд╣рд╛ рдирд┐рд░реНрдгрдп
traceparentflags рдордзреВрди рдкреБрдвреЗ рдЬрд╛рддреЛ. рд╕реНрд╡рд╕реНрдд рдЖрдгрд┐ рд╕реЛрдкреЗ, рдкрдг trace рдЕрдпрд╢рд╕реНрд╡реА рд╣реЛрдИрд▓ рдХреА рд╣рд│реВ рд╣реЛрдИрд▓ рд╣реЗ рдХреЛрдгрд╛рд▓рд╛рд╣реА рдХрд│рдгреНрдпрд╛рдЖрдзреАрдЪ рддреЗ рдард░рд╡рддреЗ. - Tail sampling тАФ trace рдкреВрд░реНрдг рдЭрд╛рд▓реНрдпрд╛рдирдВрддрд░, Collector рдордзреНрдпреЗ рдард░рд╡рдгреЗ: рдкреНрд░рддреНрдпреЗрдХ error, рдкреНрд░рддреНрдпреЗрдХ рд╣рд│реВ trace, рдЖрдгрд┐ рдмрд╛рдХреАрдЪреНрдпрд╛рдВрдЪрд╛ рдПрдХ рдирдореБрдирд╛ рдареЗрд╡рд╛. рддреНрдпрд╛рд╕рд╛рдареА рдПрдХрд╛ trace рдЪреЗ рд╕рдЧрд│реЗ spans рдПрдХрд╛рдЪ Collector рд╡рд░ рд▓рд╛рдЧрддрд╛рдд (trace id рдиреБрд╕рд╛рд░ load-balancing рдХрд░рдгрд╛рд░рд╛ layer рд╡рд╛рдкрд░рд╛) рдЖрдгрд┐ traces рд╕рдВрдкреЗрдкрд░реНрдпрдВрдд рдареЗрд╡рдгреНрдпрд╛рд╕рд╛рдареА memory рд▓рд╛рдЧрддреЗ.
- Semantic conventions тАФ attributes рдЪреА рд╕рд╛рдорд╛рдпрд┐рдХ рдирд╛рд╡реЗ:
service.name,http.request.method,http.response.status_code,http.route,url.path,db.systemтАж рдкреНрд░рддреНрдпреЗрдХ service рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ tool рддреАрдЪ рдирд╛рд╡реЗ рд╡рд╛рдкрд░рддреЗ, рдореНрд╣рдгреВрди рдПрдХ query рд╕рдЧрд│реАрдХрдбреЗ рдЪрд╛рд▓рддреЗ. (рдЬреБрдиреНрдпрд╛ рдЖрд╡реГрддреНрддреНрдпрд╛http.methodрдЖрдгрд┐http.status_codeрд╡рд╛рдкрд░рдд; stable HTTP conventions рдиреА рддреНрдпрд╛рдВрдЪреА рдирд╛рд╡реЗ рдмрджрд▓рд▓реА.)
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг standard рдирд╕рддрд╛рдирд╛, рдкреНрд░рддреНрдпреЗрдХ vendor рдЪрд╛ рд╕реНрд╡рддрдГрдЪрд╛ agent рдЖрдгрд┐ рд╕реНрд╡рддрдГрдЪреА library рд╣реЛрддреА. Backend рдмрджрд▓рдгреЗ рдореНрд╣рдгрдЬреЗ рдкреНрд░рддреНрдпреЗрдХ service рдкреБрдиреНрд╣рд╛ instrument рдХрд░рдгреЗ. OTel рд╕рд╣, app Collector рд╢реА OTLP рдордзреНрдпреЗ рдмреЛрд▓рддреЗ, рдЖрдгрд┐ Collector рдордзреНрдпреЗрдЪ рддреБрдореНрд╣реА backends рдирд┐рд╡рдбрддрд╛, рдЧреБрдкрд┐рддреЗ рдХрд╛рдвреВрди рдЯрд╛рдХрддрд╛, рдЖрдгрд┐ рдЦрд░реНрдЪ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддрд╛ тАФ рдореБрдЦреНрдпрддрдГ sampling рдиреЗ. рд╡реНрдпрд╕реНрдд рдорд╛рд░реНрдЧрд╛рд╡рд░рдЪреНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ request рдЪрд╛ trace рдШреЗрдгреЗ рдорд╣рд╛рдЧ рдЕрд╕рддреЗ; рдпрд╛рджреГрдЪреНрдЫрд┐рдХ 10% рдЪрд╛ trace рдШреЗрддрд▓рд╛ рддрд░ рддреБрдореНрд╣рд╛рд▓рд╛ рд╣рд╡рд╛ рдЕрд╕рд▓реЗрд▓рд╛ рдПрдХрдореЗрд╡ error trace рдЧрд│реВ рд╢рдХрддреЛ. Tail sampling рд░реЛрдЪрдХ traces рдареЗрд╡рддреЗ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
obs/signals.py рдордзреАрд▓ Collector(slow_ms=500, keep_1_in=10) рд╣рд╛ рдПрдХ
tail sampler рдЖрд╣реЗ: export(traces) рдкреНрд░рддреНрдпреЗрдХ рдкреВрд░реНрдг рдЭрд╛рд▓реЗрд▓рд╛ trace рдкрд╛рд╣рддреЛ рдЖрдгрд┐ рддреНрдпрд╛рдд error рдЕрд╕реЗрд▓,
рдХрд┐рдВрд╡рд╛ рддреЛ slow_ms рдкреЗрдХреНрд╖рд╛ рд╣рд│реВ рдЕрд╕реЗрд▓, рдХрд┐рдВрд╡рд╛ рддреЛ рджрд░ keep_1_in-рд╡рд╛ trace рдЕрд╕реЗрд▓, рддрд░ рддреЛ рдареЗрд╡рддреЛ; рдмрд╛рдХреАрдЪреЗ
рдЯрд╛рдХрд▓реЗ рдЬрд╛рддрд╛рдд. рддреЛ (kept, dropped) рдкрд░рдд рдХрд░рддреЛ. otel() 1,000 traces рдмрдирд╡рддреЗ: рдмрд╣реБрддреЗрдХрд╛рдВрдирд╛ 90тАУ389 ms рд▓рд╛рдЧрддрд╛рдд,
рджрд░ 97 рд╡рд╛ рд╣рд│реВ рдЕрд╕рддреЛ (+900 ms) рдЖрдгрд┐ рджрд░ 250 рд╡реНрдпрд╛рдд error рдЕрд╕рддреЗ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
Tail-sampling рдЪрд╛ рдирд┐рдпрдо рдмрджрд▓рд╛, рдордЧ head sampling рд╢реА рддреБрд▓рдирд╛ рдХрд░рд╛ (рд╕реБрд░реБрд╡рд╛рддреАрд▓рд╛рдЪ, рдХрд╛рд╣реАрд╣реА рди рдХрд│рддрд╛ 10 рдкреИрдХреА 1 рдард░рд╡рдгреЗ):
python3 obs/demo.py otel
python3 - <<'EOF'
import sys; sys.path.insert(0, "obs"); from signals import Collector
traces = [dict(id=i, ms=90 + (i * 53) % 300 + (900 if i % 97 == 0 else 0), error=(i % 250 == 0)) for i in range(1, 1001)]
for slow_ms, k in ((500, 10), (500, 100), (300, 10), (1000, 1000)):
kept, dropped = Collector(slow_ms=slow_ms, keep_1_in=k).export(traces)
print(f"keep errors + traces > {slow_ms:>4} ms + 1 in {k:<4} тЖТ kept {kept:>3}, dropped {dropped}")
head = [t for t in traces if t["id"] % 10 == 3]
print(f"head sampling 1 in 10 (decided at the start) тЖТ kept {len(head)} ┬╖ errors kept {sum(t['error'] for t in head)} of 4 ┬╖ slow kept {sum(t['ms'] > 500 for t in head)} of 10")
EOF
python3 obs/test_obs.py
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
otel рд╣реЗ print рдХрд░рддреЗ:
тФАтФА OpenTelemetry: one SDK in the app тЖТ the Collector тЖТ any backend (Tempo, Jaeger, X-Ray, DatadogтАж)
app (SDK: traces, metrics, logs) тЖТ OTLP тЖТ collector (receive тЖТ batch тЖТ sample тЖТ export) тЖТ backends
тФАтФА 1,000 traces, tail sampling (keep every error and every trace > 500 ms, 1 in 10 of the rest) тЖТ kept 113, dropped 887
all 4 error traces and all 10 slow traces survive тАФ the boring ones are sampled
semantic conventions: http.request.method, http.response.status_code, service.name тАФ the same names everywhere
рддреБрдордЪрд╛ snippet рд╣реЗ print рдХрд░рддреЛ:
keep errors + traces > 500 ms + 1 in 10 тЖТ kept 113, dropped 887
keep errors + traces > 500 ms + 1 in 100 тЖТ kept 24, dropped 976
keep errors + traces > 300 ms + 1 in 10 тЖТ kept 377, dropped 623
keep errors + traces > 1000 ms + 1 in 1000 тЖТ kept 15, dropped 985
head sampling 1 in 10 (decided at the start) тЖТ kept 100 ┬╖ errors kept 0 of 4 ┬╖ slow kept 1 of 10
Tests рдордзреНрдпреЗ тЬЕ L06 tail sampling keeps every error and every slow trace рдЕрд╕рддреЗ.
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
100 рдкреИрдХреА 1 рд╡рд░рдЪреНрдпрд╛ tail sampling рдиреЗ 1,000 рдРрд╡рдЬреА 24 traces рд╕рд╛рдард╡рд▓реЗ тАФ рдЖрдгрд┐ рддрд░реАрд╣реА рдкреНрд░рддреНрдпреЗрдХ error рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╣рд│реВ trace рдареЗрд╡рд▓рд╛. "рд╣рд│реВ" рдЪреА рд░реЗрд╖рд╛ 300 ms рдкрд░реНрдпрдВрдд рдЦрд╛рд▓реА рдЖрдгрд▓реНрдпрд╛рдиреЗ storage рддрд┐рдкреНрдкрдЯ рдЭрд╛рд▓реЗ (377), рдХрд╛рд░рдг рдЕрдиреЗрдХ рд╕рд╛рдорд╛рдиреНрдп traces 300 ms рдУрд▓рд╛рдВрдбрддрд╛рдд: рдорд░реНрдпрд╛рджрд╛ рд╣рд╛ рдЦрд░реНрдЪрд╛рдЪрд╛ рдирд┐рд░реНрдгрдп рдЖрд╣реЗ. Head sampling рдиреЗ рдкрд╣рд┐рд▓реНрдпрд╛ рдирд┐рдпрдорд╛рдЗрддрдХреАрдЪ рд╕рдВрдЦреНрдпрд╛ рдареЗрд╡рд▓реА (100 рд╡рд┐рд░реБрджреНрдз 113) рдкрдг 4 рдкреИрдХреА рдПрдХрд╣реА error рдирд╛рд╣реА рдЖрдгрд┐ 10 рдкреИрдХреА рдлрдХреНрдд 1 рд╣рд│реВ trace рдареЗрд╡рд▓рд╛ тАФ рддреНрдпрд╛рдиреЗ рдХрд│рдгреНрдпрд╛рдЖрдзреАрдЪ рдирд┐рд╡рдб рдХреЗрд▓реА.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- рдХрдореА рджрд░рд╛рдиреЗ head sampling рдХрд░рдгреЗ рдЖрдгрд┐ рдордЧ error trace рдХрд╛ рдЧрд╛рдпрдм рдЖрд╣реЗ рдпрд╛рдЪреЗ рдЖрд╢реНрдЪрд░реНрдп рд╡рд╛рдЯрдгреЗ
- trace id рдиреБрд╕рд╛рд░ routing рди рдХрд░рддрд╛ рдЕрдиреЗрдХ Collectors рд╡рд░ tail sampling тАФ рдкреНрд░рддреНрдпреЗрдХрд╛рд▓рд╛ рдЕрд░реНрдзрд╛рдЪ trace рджрд┐рд╕рддреЛ
- Collector рдордзреНрдпреЗ
memory_limiterрдирд╛рд╣реА тАФ traffic рдЪрд╛ рдПрдХ spike out-of-memory crash рдмрдирддреЛ - semantic conventions рд╡рд╛рдкрд░рдгреНрдпрд╛рдРрд╡рдЬреА рдкреНрд░рддреНрдпреЗрдХ team рдиреЗ рд╕реНрд╡рддрдГрдЪреА attribute names рд╢реЛрдзреВрди рдХрд╛рдврдгреЗ
service.nameresource attribute рдирд╛рд╣реА тАФ рдкреНрд░рддреНрдпреЗрдХ spanunknown_serviceрдореНрд╣рдгреВрди рджрд┐рд╕рддреЛ- рдкреНрд░рддреНрдпреЗрдХ app рдордзреВрди рдереЗрдЯ vendor рдХрдбреЗ export рдХрд░рдгреЗ, рддреНрдпрд╛рдореБрд│реЗ backend рдмрджрд▓рдгреЗ рдореНрд╣рдгрдЬреЗ рдкреНрд░рддреНрдпреЗрдХ app рдкреБрдиреНрд╣рд╛ deploy рдХрд░рдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
On a real account тАФ Collector рдХрдбреЗ OTLP exporter рд╕рд╣ Python SDK (packages
opentelemetry-sdk рдЖрдгрд┐ opentelemetry-exporter-otlp):
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.trace.sampling import ParentBased, ALWAYS_ON
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
provider = TracerProvider(
resource=Resource.create({"service.name": "results-api", "service.version": "v41",
"deployment.environment": "production"}),
sampler=ParentBased(ALWAYS_ON), # send everything; the Collector tail-samples
)
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(endpoint="http://otel-collector:4317", insecure=True)))
trace.set_tracer_provider(provider)
рдХрд┐рдВрд╡рд╛ code рди рдмрджрд▓рддрд╛ (auto-instrumentation):
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
OTEL_SERVICE_NAME=results-api OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 \
opentelemetry-instrument python app.py
Tail sampling рдЕрд╕рд▓реЗрд▓реА Collector pipeline тАФ errors рдареЗрд╡рд╛, рд╣рд│реВ traces рдареЗрд╡рд╛, рдмрд╛рдХреАрдЪреЗ 10%
рдареЗрд╡рд╛ (tail_sampling Collector рдЪреНрдпрд╛ contrib distribution рдордзреНрдпреЗ рдЖрд╣реЗ):
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 20
tail_sampling:
decision_wait: 10s # wait for late spans before deciding
policies:
- name: errors
type: status_code
status_code: {status_codes: [ERROR]}
- name: slow
type: latency
latency: {threshold_ms: 500}
- name: the-rest
type: probabilistic
probabilistic: {sampling_percentage: 10}
batch: {}
exporters:
otlp/tempo:
endpoint: tempo:4317
tls:
insecure: true
prometheusremotewrite:
endpoint: http://prometheus:9090/api/v1/write
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, tail_sampling, batch]
exporters: [otlp/tempo]
metrics:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [prometheusremotewrite]
AWS рд╡рд░, ADOT Collector (AWS Distro for OpenTelemetry) X-Ray рдЖрдгрд┐ CloudWatch рд╕рд╛рдареА exporters рдЬреЛрдбрддреЛ; Datadog Agent рдЖрдгрд┐ Datadog рдЪрд╛ Collector exporter рд╕реБрджреНрдзрд╛ OTLP рд╕реНрд╡реАрдХрд╛рд░рддрд╛рдд.
ЁЯПн Production рдордзреНрдпреЗ рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкрд╣рд┐рд▓реНрдпрд╛ рджрд┐рд╡рд╕рд╛рдкрд╛рд╕реВрдирдЪ рддреБрдордЪреЗ apps рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ backend рдпрд╛рдВрдЪреНрдпрд╛рдордзреНрдпреЗ рдПрдХ Collector рдареЗрд╡рд╛. рддрд┐рдереЗрдЪ рддреБрдореНрд╣реА рдЧреБрдкрд┐рддреЗ рдХрд╛рдврддрд╛, sample рдХрд░рддрд╛, рдЖрдгрд┐ vendors рдмрджрд▓рддрд╛ тАФ рдПрдХрд╛рд╣реА service рд▓рд╛ рд╣рд╛рдд рди рд▓рд╛рд╡рддрд╛.
тПня╕П рдкреБрдвреЗ
Signals рд╡рд╛рд╣реВ рд▓рд╛рдЧрд▓реЗ рдЖрд╣реЗрдд. рдЖрддрд╛ metrics рд╕рд╛рдард╡рд╛, рддреНрдпрд╛рдВрдирд╛ рдкреНрд░рд╢реНрди рд╡рд┐рдЪрд╛рд░рд╛ рдЖрдгрд┐ рддреНрдпрд╛рдВрдЪреЗ рдЪрд┐рддреНрд░ рдХрд╛рдврд╛: Prometheus рдЖрдгрд┐ Grafana.
git checkout lesson-07-prometheus-grafana