File indexing completed on 2026-11-09 10:47:23
0001
0002 """Take live records off the computing centre's epicprod-live screen.
0003
0004 Writes one ``live_cleared`` record to the epicprod action stream naming the
0005 cleared log record ids and the reason (COMP_SNAPSHOT.md, Live). The comp
0006 snapshot leaves the named records out of the screen; the records themselves
0007 are unchanged on the logs page.
0008
0009 source ~/.env
0010 python scripts/live-clear.py 6221565 6223208 --reason "door probe fixed 04:37"
0011
0012 Environment: SWF_MONITOR_HTTP_URL (the monitor base URL) and SWF_API_TOKEN.
0013 """
0014
0015 import argparse
0016 import json
0017 import os
0018 import sys
0019 import urllib.error
0020 import urllib.request
0021 from datetime import datetime, timezone
0022
0023
0024 def main():
0025 parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
0026 parser.add_argument('ids', nargs='+', type=int, help='log record ids')
0027 parser.add_argument('--reason', required=True,
0028 help='why they are off the screen')
0029 parser.add_argument('--by', default=os.environ.get('USER', ''),
0030 help='who cleared them (default: $USER)')
0031 args = parser.parse_args()
0032
0033 base = os.environ.get('SWF_MONITOR_HTTP_URL', '').rstrip('/')
0034 token = os.environ.get('SWF_API_TOKEN', '')
0035 if not base or not token:
0036 sys.exit('SWF_MONITOR_HTTP_URL and SWF_API_TOKEN must be set '
0037 '(source ~/.env)')
0038
0039 ids = sorted(set(args.ids))
0040 summary = (f"cleared {len(ids)} record(s) from the epicprod-live screen: "
0041 f"{', '.join(str(i) for i in ids)}; {args.reason}")
0042 body = {
0043 'app_name': 'epicprod',
0044 'instance_name': 'live-clear',
0045 'timestamp': datetime.now(timezone.utc).isoformat(),
0046 'level': 20,
0047 'levelname': 'INFO',
0048 'message': summary,
0049 'module': 'live_clear',
0050 'funcname': 'main',
0051 'lineno': 0,
0052 'process': os.getpid(),
0053 'thread': 0,
0054 'extra_data': {
0055 'action': 'live_cleared',
0056 'outcome': 'ok',
0057 'sublevel': 'low',
0058 'live_default': False,
0059 'username': args.by,
0060 'cleared_ids': ids,
0061 'reason': args.reason,
0062 'summary': summary,
0063 },
0064 }
0065 request = urllib.request.Request(
0066 f'{base}/api/logs/', data=json.dumps(body).encode(), method='POST',
0067 headers={'Content-Type': 'application/json',
0068 'Authorization': f'Token {token}'})
0069 try:
0070 with urllib.request.urlopen(request, timeout=30) as response:
0071 record = json.loads(response.read() or b'{}')
0072 except urllib.error.HTTPError as exc:
0073 sys.exit(f'HTTP {exc.code} from {base}/api/logs/: '
0074 f'{exc.read()[:500].decode(errors="replace")}')
0075 except urllib.error.URLError as exc:
0076 sys.exit(f'{base}/api/logs/ unreachable: {exc.reason}')
0077 print(f"live_cleared record {record.get('id', '?')}: {summary}")
0078
0079
0080 if __name__ == '__main__':
0081 main()