DealDocumentScreening/deploy/observability/vector-config.yaml
febux b279d6c61a Switch observability to passive collection: remove OTLP push, Vector replaces otel-collector
- core/telemetry.py is now a no-op (no opentelemetry imports); entrypoints
  no longer call setup/shutdown telemetry
- Remove all opentelemetry-* deps from pyproject groups; regenerate uv.lock
- Drop otel_exporter_otlp_endpoint/otel_service_name settings; sentry and
  auth use "contract-check" instead
- Stop publishing worker metrics ports; bind API metrics to 127.0.0.1 by
  default via API_METRICS_BIND_HOST
- Replace otel-collector with Vector in observer profile (docker_logs +
  prometheus_scrape -> OpenObserve); add deploy/observability/vector-config.yaml
- Update .env.example, docs (ARCHITECTURE, DEPLOY), README, Makefile
- Rewrite tests/unit/test_telemetry.py for the no-op implementation
2026-09-06 19:17:08 +03:00

115 lines
3.5 KiB
YAML

# Vector configuration for the `observer` profile (passive observability).
#
# Vector reads container logs from the local Docker socket and scrapes service
# /metrics endpoints inside the compose network, then forwards logs and metrics
# to OpenObserve. The application itself does not push telemetry.
# -----------------------------------------------------------------------------
# Sources
# -----------------------------------------------------------------------------
sources:
docker_logs:
type: docker_logs
# Read from the local Docker socket mounted by compose.
docker_host: unix:///var/run/docker.sock
include_labels:
- com.docker.compose.project=dealdocumentscreening
service_metrics:
type: prometheus_scrape
endpoints:
- http://api:8000/metrics
- http://worker-extract:9101/metrics
- http://worker-analyze:9102/metrics
- http://worker-prescreen:9104/metrics
- http://worker-billing:9105/metrics
- http://worker-notify:9103/metrics
scrape_interval_secs: 15
# Auth header is injected via a remap transform when METRICS_BEARER_TOKEN is set.
# -----------------------------------------------------------------------------
# Transforms
# -----------------------------------------------------------------------------
transforms:
enrich_logs:
type: remap
inputs:
- docker_logs
source: |
# Keep the raw message and container name; derive a short service label.
.container = .container_name ?? .container_id ?? "unknown"
.service = .container_name ?? "unknown"
# If the log line is JSON from our structured logger, merge its fields
# without overwriting Vector/container metadata.
raw = .message ?? ""
if is_string(raw) {
parsed, err = parse_json(raw)
if err == null && is_object(parsed) {
for_each(parsed) -> |key, value| {
if !exists(.) || !exists(.[key]) {
.[key] = value
}
}
# Ensure OpenObserve can filter by the canonical service label even when
# the JSON payload carries its own "service" field.
if exists(parsed.service) {
.service = parsed.service
}
if exists(parsed.correlation_id) {
.correlation_id = parsed.correlation_id
}
}
}
# Trim container runtime prefixes for a cleaner service label.
.service = replace(.service, "^contract_check-", "")
add_metrics_auth:
type: remap
inputs:
- service_metrics
source: |
token = get_env_var("METRICS_BEARER_TOKEN") ?? ""
if token != "" {
.headers = {"Authorization": "Bearer " + token}
}
# -----------------------------------------------------------------------------
# Sinks
# -----------------------------------------------------------------------------
sinks:
openobserve_logs:
type: http
inputs:
- enrich_logs
uri: http://openobserve:5080/openobserve/api/default/_json
method: post
auth:
strategy: basic
user: ""
password: ${OPENOBSERVE_AUTH_TOKEN}
encoding:
codec: json
batch:
max_events: 100
timeout_secs: 1
request:
headers:
Content-Type: application/json
openobserve_metrics:
type: prometheus_remote_write
inputs:
- add_metrics_auth
endpoint: http://openobserve:5080/openobserve/api/default/prometheus/api/v1/write
auth:
strategy: basic
user: ""
password: ${OPENOBSERVE_AUTH_TOKEN}
batch:
max_events: 100
timeout_secs: 1