feat: add bgp observability and admin ui improvements
This commit is contained in:
@@ -9,10 +9,12 @@ import io
|
||||
|
||||
from app.core.collected_data_fields import get_metadata_field
|
||||
from app.core.countries import COUNTRY_OPTIONS, get_country_search_variants, normalize_country
|
||||
from app.core.time import to_iso8601_utc
|
||||
from app.db.session import get_db
|
||||
from app.models.user import User
|
||||
from app.core.security import get_current_user
|
||||
from app.models.collected_data import CollectedData
|
||||
from app.models.datasource import DataSource
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -100,11 +102,13 @@ def build_search_rank_sql(search: Optional[str]) -> str:
|
||||
"""
|
||||
|
||||
|
||||
def serialize_collected_row(row) -> dict:
|
||||
def serialize_collected_row(row, source_name_map: dict[str, str] | None = None) -> dict:
|
||||
metadata = row[7]
|
||||
source = row[1]
|
||||
return {
|
||||
"id": row[0],
|
||||
"source": row[1],
|
||||
"source": source,
|
||||
"source_name": source_name_map.get(source, source) if source_name_map else source,
|
||||
"source_id": row[2],
|
||||
"data_type": row[3],
|
||||
"name": row[4],
|
||||
@@ -121,12 +125,17 @@ def serialize_collected_row(row) -> dict:
|
||||
"rmax": get_metadata_field(metadata, "rmax"),
|
||||
"rpeak": get_metadata_field(metadata, "rpeak"),
|
||||
"power": get_metadata_field(metadata, "power"),
|
||||
"collected_at": row[8].isoformat() if row[8] else None,
|
||||
"reference_date": row[9].isoformat() if row[9] else None,
|
||||
"collected_at": to_iso8601_utc(row[8]),
|
||||
"reference_date": to_iso8601_utc(row[9]),
|
||||
"is_valid": row[10],
|
||||
}
|
||||
|
||||
|
||||
async def get_source_name_map(db: AsyncSession) -> dict[str, str]:
|
||||
result = await db.execute(select(DataSource.source, DataSource.name))
|
||||
return {row[0]: row[1] for row in result.fetchall()}
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def list_collected_data(
|
||||
mode: str = Query("current", description="查询模式: current/history"),
|
||||
@@ -188,10 +197,11 @@ async def list_collected_data(
|
||||
|
||||
result = await db.execute(query, params)
|
||||
rows = result.fetchall()
|
||||
source_name_map = await get_source_name_map(db)
|
||||
|
||||
data = []
|
||||
for row in rows:
|
||||
data.append(serialize_collected_row(row[:11]))
|
||||
data.append(serialize_collected_row(row[:11], source_name_map))
|
||||
|
||||
return {
|
||||
"total": total,
|
||||
@@ -221,6 +231,7 @@ async def get_data_summary(
|
||||
""")
|
||||
)
|
||||
rows = result.fetchall()
|
||||
source_name_map = await get_source_name_map(db)
|
||||
|
||||
by_source = {}
|
||||
total = 0
|
||||
@@ -229,9 +240,10 @@ async def get_data_summary(
|
||||
data_type = row[1]
|
||||
count = row[2]
|
||||
|
||||
if source not in by_source:
|
||||
by_source[source] = {}
|
||||
by_source[source][data_type] = count
|
||||
source_key = source_name_map.get(source, source)
|
||||
if source_key not in by_source:
|
||||
by_source[source_key] = {}
|
||||
by_source[source_key][data_type] = count
|
||||
total += count
|
||||
|
||||
# Total by source
|
||||
@@ -249,7 +261,14 @@ async def get_data_summary(
|
||||
return {
|
||||
"total_records": total,
|
||||
"by_source": by_source,
|
||||
"source_totals": [{"source": row[0], "count": row[1]} for row in source_rows],
|
||||
"source_totals": [
|
||||
{
|
||||
"source": row[0],
|
||||
"source_name": source_name_map.get(row[0], row[0]),
|
||||
"count": row[1],
|
||||
}
|
||||
for row in source_rows
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -269,9 +288,13 @@ async def get_data_sources(
|
||||
""")
|
||||
)
|
||||
rows = result.fetchall()
|
||||
source_name_map = await get_source_name_map(db)
|
||||
|
||||
return {
|
||||
"sources": [row[0] for row in rows],
|
||||
"sources": [
|
||||
{"source": row[0], "source_name": source_name_map.get(row[0], row[0])}
|
||||
for row in rows
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -334,7 +357,8 @@ async def get_collected_data(
|
||||
detail="数据不存在",
|
||||
)
|
||||
|
||||
return serialize_collected_row(row)
|
||||
source_name_map = await get_source_name_map(db)
|
||||
return serialize_collected_row(row, source_name_map)
|
||||
|
||||
|
||||
def build_where_clause(
|
||||
@@ -482,8 +506,8 @@ async def export_csv(
|
||||
get_metadata_field(row[7], "value"),
|
||||
get_metadata_field(row[7], "unit"),
|
||||
json.dumps(row[7]) if row[7] else "",
|
||||
row[8].isoformat() if row[8] else "",
|
||||
row[9].isoformat() if row[9] else "",
|
||||
to_iso8601_utc(row[8]) or "",
|
||||
to_iso8601_utc(row[9]) or "",
|
||||
row[10],
|
||||
]
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user