Přeskočit na hlavní obsah

Telemetrie

UCS hosty obsahují vestavěný observability stack (Grafana / Loki / Tempo / Prometheus / OpenTelemetry Collector). Aplikace mají posílat metriky, logy a trace do lokálního OpenTelemetry Collectoru, který každý signál přepošle do příslušného backendu.

Přehled pro administrátory najdete v sekci Observabilita.

Endpoint

OpenTelemetry Collector naslouchá lokálně na:

EndpointProtokolPoužijte pro
localhost:4317OTLP / gRPCAplikace na serveru s OTel SDK
localhost:4318OTLP / HTTPAplikace preferující HTTP, nebo curl/ruční odesílání
https://<host>/otel/v1/*OTLP / HTTPSExterní klienti (prohlížeče, mobilní aplikace) — přes Traefik

Všechny tři endpointy přijímají všechny tři signály (trace, metriky, logy). HTTP cesty pro OTLP/HTTP endpoint jsou standardní:

  • POST /v1/traces
  • POST /v1/metrics
  • POST /v1/logs

Traefik route prefix /otel odstraní, takže POST /otel/v1/traces se předá lokálnímu collectoru jako POST /v1/traces.

Směrování signálů do backendů

Pipelines collectoru (definované v /etc/otelcol-contrib/config.yaml) směrují signály takto:

SignálOTLP cestaBackendKde si je prohlédnete
Trace/v1/tracesTempoGrafana → Explore → Tempo
Metriky/v1/metricsPrometheusGrafana → Explore → Prometheus (přes remote-write)
Logy/v1/logsLokiGrafana → Explore → Loki

Bez ohledu na typ signálu používejte stejný endpoint — collector demultiplexuje podle HTTP cesty nebo gRPC metody.

Instrumentace aplikace

Python

Nainstalujte OTel SDK a OTLP exporter:

pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp

Minimální příklad — odešle trace z Python služby:

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.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter

resource = Resource.create({"service.name": "ucs-api"})
provider = TracerProvider(resource=resource)
provider.add_span_processor(
BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4317", insecure=True))
)
trace.set_tracer_provider(provider)

tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("handle-request"):
# ... váš kód ...
pass

Pro Python aplikace preferujte auto-instrumentaci HTTP frameworků, databází atd. — žádný kód v aplikaci navíc:

pip install opentelemetry-instrumentation
opentelemetry-bootstrap --action=install # nainstaluje instrumentace pro detekované knihovny
opentelemetry-instrument --traces_exporter otlp \
--metrics_exporter otlp \
--logs_exporter otlp \
--exporter_otlp_endpoint http://localhost:4317 \
python your_app.py

Node.js

npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-grpc
const { NodeSDK } = require('@opentelemetry/sdk-node')
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc')
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')

const sdk = new NodeSDK({
serviceName: 'ucs-operator',
traceExporter: new OTLPTraceExporter({ url: 'http://localhost:4317' }),
instrumentations: [getNodeAutoInstrumentations()],
})
sdk.start()

Ostatní jazyky

OpenTelemetry má SDK pro většinu hlavních jazyků — Java, Go, .NET, Rust, PHP, Ruby. URL OTLP endpointu je všude stejné: http://localhost:4317 (gRPC) nebo http://localhost:4318 (HTTP).

Telemetrie z prohlížeče / mobilního klienta

Pro kód běžící na straně klienta (webové stránky, mobilní aplikace) použijte veřejný HTTPS endpoint přes Traefik:

import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'

const provider = new WebTracerProvider({
resource: new Resource({ 'service.name': 'ucs-admin-ui' }),
})
provider.addSpanProcessor(new BatchSpanProcessor(new OTLPTraceExporter({
url: 'https://váš-ucs-host/otel/v1/traces',
})))
provider.register()

Traefik route obsahuje CORS middleware, rate-limiting a limit velikosti těla požadavku — viz /etc/traefik/conf.d/07_otel.yaml.

Ruční odesílání (testování / jednorázové akce)

Hodí se pro ověření konektivity, ladění pipeline nebo ad-hoc události ze shell skriptů.

Odeslat log přes curl:

NOW=$(date +%s%N)
curl -X POST -H "Content-Type: application/json" \
http://localhost:4318/v1/logs \
-d "{\"resourceLogs\":[{\"resource\":{\"attributes\":[{\"key\":\"service.name\",\"value\":{\"stringValue\":\"shell-script\"}}]},\"scopeLogs\":[{\"scope\":{},\"logRecords\":[{\"timeUnixNano\":\"$NOW\",\"severityText\":\"INFO\",\"body\":{\"stringValue\":\"hello from shell\"}}]}]}]}"

Odeslat trace:

TRACE=$(openssl rand -hex 16); SPAN=$(openssl rand -hex 8)
NOW=$(date +%s%N); END=$((NOW + 1000000))
curl -X POST -H "Content-Type: application/json" \
http://localhost:4318/v1/traces \
-d "{\"resourceSpans\":[{\"resource\":{\"attributes\":[{\"key\":\"service.name\",\"value\":{\"stringValue\":\"shell-script\"}}]},\"scopeSpans\":[{\"scope\":{},\"spans\":[{\"traceId\":\"$TRACE\",\"spanId\":\"$SPAN\",\"name\":\"test-span\",\"kind\":1,\"startTimeUnixNano\":\"$NOW\",\"endTimeUnixNano\":\"$END\"}]}]}]}"
echo "TRACE=$TRACE"

Odeslat metriku:

NOW=$(date +%s%N)
curl -X POST -H "Content-Type: application/json" \
http://localhost:4318/v1/metrics \
-d "{\"resourceMetrics\":[{\"resource\":{\"attributes\":[{\"key\":\"service.name\",\"value\":{\"stringValue\":\"shell-script\"}}]},\"scopeMetrics\":[{\"scope\":{},\"metrics\":[{\"name\":\"shell_test_counter\",\"sum\":{\"dataPoints\":[{\"asInt\":\"1\",\"timeUnixNano\":\"$NOW\"}],\"aggregationTemporality\":2,\"isMonotonic\":true}}]}]}]}"

Každý request by měl vrátit HTTP 200 s tělem {"partialSuccess":{}}.

Konvence

Resource atributy

Vždy nastavte minimálně service.name u každého odeslaného signálu — Grafana data podle tohoto atributu seskupuje. Doporučené dodatky:

  • service.namespace — např. ucs, uphone, operator
  • service.version — verze vaší služby
  • deployment.environmentproduction, staging, development

Jsou součástí OpenTelemetry Resource semantic conventions.

Pojmenování span / metrik

Dodržujte OTel semantické konvence pro běžné atributy (HTTP, DB, RPC). Například HTTP servery by měly emitovat spany pojmenované <METHOD> <route> s atributy http.request.method, http.response.status_code atd. Auto-instrumentace to dělají automaticky pro podporované knihovny.

Sampling

Pro služby s velkým provozem nakonfigurujte head-based nebo tail-based sampling v SDK pro omezení objemu. Výchozí OTel SDK sampler je parentbased_always_on, který emituje všechny spany — vhodné pro málo zatížené backendy, příliš drahé pro horké HTTP servery.

Propojení log/trace

Při emitování logu z kontextu, kde je aktivní trace (typicky uvnitř instrumentovaného HTTP handleru), SDK automaticky připojí trace_id a span_id k záznamu logu. V Grafaně v Loki můžete pak kliknout na řádek logu a skočit na odpovídající trace v Tempo.

Prohlížení dat

Otevřete Grafanu na https://<adresa-serveru>/grafana/ (případně http://<adresa-serveru>:3030/grafana/ přímo, bez proxy). Výchozí přihlášení admin/admin. Datasource pro Loki, Prometheus a Tempo jsou již předkonfigurované.

Explore (volné dotazy): ☰ → Explore, vyberte datasource.

  • Loki dotaz: {service_name="ucs-api"} |= "error"
  • Prometheus dotaz: rate(http_server_request_duration_seconds_count{service_name="ucs-api"}[5m])
  • Tempo dotaz: vložte trace_id přímo, nebo použijte TraceQL.

Troubleshooting

Aplikace zdánlivě odesílá telemetrii, ale v Grafaně nic není:

  1. Sledujte v collectoru chyby exportu:
    journalctl -u otelcol-contrib -n 50 --no-pager
  2. Ověřte, že collector data přijal — POST vracející 200 znamená, že byla přijata. Pokud selhává backend exportér (Loki / Tempo / Prometheus), chyba se objeví v logu collectoru.
  3. Ověřte v Grafaně časový rozsah — Explore standardně zobrazuje poslední hodinu.

OTLP HTTP vrací 415 Unsupported Media Type — ujistěte se, že hlavička Content-Type je application/json (ne text/plain).

Vyhledání trace ID vrací v Tempu 404 — Tempo má krátké zpoždění při ingestu (vteřiny). Počkejte a opakujte. Také ověřte, že trace ID je přesně 32 znaků malých písmen hex.

Logy se objevují, ale pole severity je prázdné — nastavte v OTLP záznamu logu jak severityText (string), tak severityNumber (integer). OTel SDK to dělají automaticky; ruční payloady potřebují obojí.