host-metrics/scripts/probe-pipeline.py
2026-09-17 22:31:35 +02:00

64 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""Send ONE uniquely tagged probe to Kafka, then verify its indexed representation.
Does not reset consumer offsets or write directly to OpenSearch. The measurement
name 'pipeline_probe' is excluded by every supplied metric visualization filter.
"""
import json
from pathlib import Path
import subprocess
import sys
import time
import urllib.error
import urllib.request
import uuid
ROOT = Path(__file__).resolve().parents[1]
def probe():
probe_id = uuid.uuid4().hex
sample = {'name': 'pipeline_probe', 'timestamp': int(time.time() * 1000),
'tags': {'host': 'pipeline-probe', 'environment': 'diagnostic',
'role': 'diagnostic', 'series': 'pipeline-probe / diagnostic', 'probe_id': probe_id},
'fields': {'value': 1.0}}
print('Publishing one diagnostic measurement to Kafka:', probe_id, flush=True)
command = ['docker', 'compose', 'exec', '-T', 'kafka', '/opt/kafka/bin/kafka-console-producer.sh',
'--bootstrap-server', 'kafka:29092', '--topic', 'host-metrics-v1',
'--producer-property', 'acks=all', '--producer-property', 'delivery.timeout.ms=15000',
'--producer-property', 'request.timeout.ms=10000', '--producer-property', 'max.block.ms=15000']
try:
sent = subprocess.run(command, cwd=ROOT, input=json.dumps(sample) + '\n', text=True,
capture_output=True, timeout=40)
except subprocess.TimeoutExpired:
print('FAIL: Kafka producer timed out. Check broker/topic/listeners.'); return 2
if sent.returncode or 'ERROR' in sent.stderr:
print(sent.stdout, sent.stderr)
print('FAIL: Kafka did not accept the probe.'); return 2
print('Producer completed; checking Data Prepper → OpenSearch for up to 60 seconds.', flush=True)
last_error = ''
for _ in range(12):
query = {'size': 1, 'query': {'term': {'tags.probe_id': probe_id}}}
request = urllib.request.Request('http://127.0.0.1:9200/host-metrics-v1-*/_search',
data=json.dumps(query).encode(), headers={'Content-Type': 'application/json'})
try:
with urllib.request.urlopen(request, timeout=5) as response:
hits = json.load(response)['hits']['hits']
if hits:
doc = hits[0]['_source']
if not doc.get('@timestamp') or doc.get('fields', {}).get('value') != 1:
print('FAIL: probe indexed with incorrect transformation:', json.dumps(doc)); return 3
print('PASS: Kafka → Data Prepper → OpenSearch is working.')
print('Index:', hits[0]['_index'], 'timestamp:', doc['@timestamp'])
print('If native host metrics are absent, inspect the Telegraf service/configuration and its Kafka connection.')
return 0
except (urllib.error.URLError, KeyError, ValueError) as error:
last_error = str(error)
time.sleep(5)
print('FAIL: probe was not found in OpenSearch within the wait window.', last_error)
print('Inspect Data Prepper startup errors, consumer lag/backlog, OpenSearch write failures and the DLQ.')
print('Probe ID (for searching again after a backlog drains):', probe_id)
return 3
if __name__ == '__main__':
sys.exit(probe())