"""Fetch feed status from the Flask backend and reshape into a DataFrame.""" import os import pandas as pd import requests import streamlit as st from feed_status.ui.status import chip_label, status_glyph BASE_URL = os.environ.get('MONTY_API_BASE_URL', 'http://localhost:5000') FEED_ID_COL = '_feed_id' FEED_COL = 'Feed' FRESH_COL = 'Fresh' STABLE_COL = 'Stable' _FIXED_COLS = (FEED_COL, FRESH_COL, STABLE_COL) _SESSION = requests.Session() @st.cache_data(ttl=120, show_spinner='Loading feed status…') def fetch_section(apipath, date=None): """Fetch one section and return (DataFrame, date_columns, details). The DataFrame is wide format with a hidden FEED_ID_COL so selected rows can be mapped back to feed_id. `details` maps feed_id → dict with the raw 'statuses' and 'status_details' from the API payload. """ url = f'{BASE_URL}{apipath}' if date: url = f'{url}/{date}' response = _SESSION.get(url, timeout=120) response.raise_for_status() return _reshape(response.json()) @st.cache_data(ttl=600, show_spinner=False) def fetch_service_links(): """Fetch the service-link config (Sentry, scheduler, AWS SWF, etc.).""" url = f'{BASE_URL}/ingestion_feed/service_links' response = _SESSION.get(url, timeout=30) response.raise_for_status() body = response.json() return body.get('supported_links', {}), body.get('service_links', {}) def get_links(feed_id, supported, links): """Return {service: url} for the feed, dropping empty URLs.""" group = supported.get(feed_id) if not group: return {} return {name: url for name, url in (links.get(group) or {}).items() if url} def _reshape(body): """Transform the API JSON payload into a wide DataFrame plus details.""" dates = list(body.get('dates', [])) rows = [] details = {} for item in body.get('data', []): feed_id = item.get('feed_id', '') statuses = item.get('status') or item.get('status_history') or {} status_details = item.get('status_details') or {} metrics = {m['name']: m['status'] for m in item.get('metrics', [])} row = { FEED_ID_COL: feed_id, FEED_COL: item.get('feed_name', ''), FRESH_COL: chip_label(metrics.get('current_status', '')), STABLE_COL: chip_label(metrics.get('stability', '')), } for d in dates: row[d] = status_glyph(statuses.get(d)) rows.append(row) details[feed_id] = { 'statuses': statuses, 'status_details': status_details, } df = pd.DataFrame(rows, columns=[FEED_ID_COL, *_FIXED_COLS, *dates]) return df, dates, details