feat: expand bgp observability surfaces
This commit is contained in:
@@ -11,6 +11,7 @@ from app.models.bgp_anomaly import BGPAnomaly
|
||||
from app.models.bgp_incident import BGPIncident
|
||||
from app.models.bgp_observation import BGPObservation
|
||||
from app.models.user import User
|
||||
from app.services.bgp_collectors import build_bgp_collector_coverage
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -108,6 +109,35 @@ async def get_bgp_event_summary(
|
||||
}
|
||||
|
||||
|
||||
@router.get("/collectors")
|
||||
async def list_bgp_collectors(
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
data = await build_bgp_collector_coverage(db, source_filter=BGP_SOURCES)
|
||||
return {
|
||||
"total": len(data),
|
||||
"data": data,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/collectors/summary")
|
||||
async def get_bgp_collector_summary(
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
collectors = await build_bgp_collector_coverage(db, source_filter=BGP_SOURCES)
|
||||
active_collectors = [item for item in collectors if item["observation_count"] > 0]
|
||||
return {
|
||||
"total": len(collectors),
|
||||
"active_collectors": len(active_collectors),
|
||||
"observed_prefixes": sum(item["prefix_count"] for item in active_collectors),
|
||||
"observed_origins": sum(item["origin_asn_count"] for item in active_collectors),
|
||||
"recent_24h_events": sum(item["recent_24h_observation_count"] for item in active_collectors),
|
||||
"recent_7d_events": sum(item["recent_7d_observation_count"] for item in active_collectors),
|
||||
}
|
||||
|
||||
|
||||
@router.get("/events/{event_id}")
|
||||
async def get_bgp_event(
|
||||
event_id: int,
|
||||
|
||||
@@ -17,6 +17,7 @@ from app.db.session import get_db
|
||||
from app.models.bgp_anomaly import BGPAnomaly
|
||||
from app.models.bgp_incident import BGPIncident
|
||||
from app.models.collected_data import CollectedData
|
||||
from app.services.bgp_collectors import build_bgp_collector_coverage
|
||||
from app.services.cable_graph import build_graph_from_data, CableGraph
|
||||
from app.services.collectors.bgp_common import RIPE_RIS_COLLECTOR_COORDS
|
||||
|
||||
@@ -417,10 +418,14 @@ def convert_bgp_anomalies_to_geojson(records: List[BGPAnomaly]) -> Dict[str, Any
|
||||
return {"type": "FeatureCollection", "features": features}
|
||||
|
||||
|
||||
def convert_bgp_collectors_to_geojson() -> Dict[str, Any]:
|
||||
def convert_bgp_collectors_to_geojson(
|
||||
coverage_by_collector: Dict[str, Dict[str, Any]] | None = None,
|
||||
) -> Dict[str, Any]:
|
||||
features = []
|
||||
coverage_by_collector = coverage_by_collector or {}
|
||||
|
||||
for collector, location in sorted(RIPE_RIS_COLLECTOR_COORDS.items()):
|
||||
coverage = coverage_by_collector.get(collector, {})
|
||||
features.append(
|
||||
{
|
||||
"type": "Feature",
|
||||
@@ -430,9 +435,27 @@ def convert_bgp_collectors_to_geojson() -> Dict[str, Any]:
|
||||
},
|
||||
"properties": {
|
||||
"collector": collector,
|
||||
"city": location.get("city"),
|
||||
"country": location.get("country"),
|
||||
"city": coverage.get("city") or location.get("city"),
|
||||
"country": coverage.get("country") or location.get("country"),
|
||||
"status": "online",
|
||||
"observation_count": coverage.get("observation_count", 0),
|
||||
"prefix_count": coverage.get("prefix_count", 0),
|
||||
"origin_asn_count": coverage.get("origin_asn_count", 0),
|
||||
"peer_asn_count": coverage.get("peer_asn_count", 0),
|
||||
"recent_24h_observation_count": coverage.get("recent_24h_observation_count", 0),
|
||||
"recent_7d_observation_count": coverage.get("recent_7d_observation_count", 0),
|
||||
"recent_24h_prefix_count": coverage.get("recent_24h_prefix_count", 0),
|
||||
"recent_7d_prefix_count": coverage.get("recent_7d_prefix_count", 0),
|
||||
"top_event_types": coverage.get("top_event_types", []),
|
||||
"latest_observed_at": coverage.get("latest_observed_at"),
|
||||
"latest_event_type": coverage.get("latest_event_type"),
|
||||
"baseline_scope": coverage.get(
|
||||
"baseline_scope",
|
||||
{
|
||||
"countries": [location.get("country")] if location.get("country") else [],
|
||||
"cities": [location.get("city")] if location.get("city") else [],
|
||||
},
|
||||
),
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -740,8 +763,17 @@ async def get_bgp_incidents_geojson(
|
||||
|
||||
|
||||
@router.get("/geo/bgp-collectors")
|
||||
async def get_bgp_collectors_geojson():
|
||||
geojson = convert_bgp_collectors_to_geojson()
|
||||
async def get_bgp_collectors_geojson(db: AsyncSession = Depends(get_db)):
|
||||
coverage = await build_bgp_collector_coverage(
|
||||
db,
|
||||
source_filter=("ris_live_bgp", "bgpstream_bgp"),
|
||||
)
|
||||
coverage_by_collector = {
|
||||
item["collector"]: item
|
||||
for item in coverage
|
||||
if item.get("collector")
|
||||
}
|
||||
geojson = convert_bgp_collectors_to_geojson(coverage_by_collector)
|
||||
return {**geojson, "count": len(geojson.get("features", []))}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user