Complete local Prometheus mapping and record live acceptance blockers
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e6f1-443f-7783-9920-a16b2ffc467f
This commit is contained in:
parent
27df597a39
commit
b6d0f78f93
11 changed files with 501 additions and 5 deletions
55
scripts/prometheus_export.py
Normal file
55
scripts/prometheus_export.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Render a validated S3 report as Prometheus text; no listener or delivery."""
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
from platform_event import translate
|
||||
from receiver import STATES, contract_check, instant, read_json
|
||||
|
||||
|
||||
def labels(values):
|
||||
def escape(value):
|
||||
return value.replace('\\', '\\\\').replace('\n', '\\n').replace('"', '\\"')
|
||||
return '{' + ','.join(f'{key}="{escape(value)}"' for key, value in values.items()) + '}'
|
||||
|
||||
|
||||
def render(report, contract, now):
|
||||
contract_check(contract)
|
||||
event = translate(report, contract)
|
||||
observed = instant(event['observed_at']).timestamp()
|
||||
if not 0 <= now.timestamp() - observed <= contract['max_event_age_seconds']:
|
||||
raise ValueError('stale or future report')
|
||||
identity = dict(stream=contract['stream'], producer=contract['producer'])
|
||||
lines = ['# HELP railiance_assurance_state Producer classification, one hot per signal.',
|
||||
'# TYPE railiance_assurance_state gauge']
|
||||
for signal, state in sorted(event['states'].items()):
|
||||
for candidate in sorted(STATES):
|
||||
key = labels(dict(identity, signal=signal, state=candidate))
|
||||
lines.append(f'railiance_assurance_state{key} {int(state == candidate)}')
|
||||
lines.extend([
|
||||
'# HELP railiance_assurance_observed_timestamp_seconds Original producer evaluation time.',
|
||||
'# TYPE railiance_assurance_observed_timestamp_seconds gauge',
|
||||
f'railiance_assurance_observed_timestamp_seconds{labels(identity)} {observed}',
|
||||
])
|
||||
return '\n'.join(lines) + '\n'
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--contract', required=True, type=Path)
|
||||
parser.add_argument('report', type=Path)
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
output = render(read_json(args.report), read_json(args.contract), datetime.now(timezone.utc))
|
||||
except (OSError, ValueError, KeyError, TypeError, AttributeError):
|
||||
print(json.dumps({'status': 'rejected', 'error': 'invalid-or-expired-report'}), file=sys.stderr)
|
||||
return 2
|
||||
sys.stdout.write(output)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue