main
py 226 lines 8.13 KB
Raw
1 import time
2 from datetime import datetime
3 from datetime import timedelta
4 from typing import List
5
6 from fastapi import APIRouter
7 from fastapi import Depends
8 from fastapi import Security
9 from loguru import logger
10 from sqlalchemy.ext.asyncio import AsyncSession
11 from sqlalchemy.future import select
12
13 from app.auth.utils import AuthHandler
14 from app.connectors.grafana.schema.reporting import GenerateReportRequest
15 from app.connectors.grafana.schema.reporting import GenerateReportResponse
16 from app.connectors.grafana.schema.reporting import GrafanaDashboardDetailsResponse
17 from app.connectors.grafana.schema.reporting import GrafanaDashboardPanelsResponse
18 from app.connectors.grafana.schema.reporting import GrafanaDashboardResponse
19 from app.connectors.grafana.schema.reporting import GrafanaGenerateIframeLinksRequest
20 from app.connectors.grafana.schema.reporting import GrafanaGenerateIframeLinksResponse
21 from app.connectors.grafana.schema.reporting import GrafanaLinksList
22 from app.connectors.grafana.schema.reporting import GrafanaOrganizationsResponse
23 from app.connectors.grafana.schema.reporting import Panel
24 from app.connectors.grafana.schema.reporting import TimeRange
25 from app.connectors.grafana.services.reporting import generate_report
26 from app.connectors.grafana.services.reporting import get_dashboard_details
27 from app.connectors.grafana.services.reporting import get_dashboards
28 from app.connectors.grafana.services.reporting import get_orgs
29 from app.connectors.models import Connectors
30 from app.db.db_session import get_db
31 from app.middleware.license import is_feature_enabled
32
33 # from app.middleware.license import is_feature_enabled
34
35 # App specific imports
36
37
38 grafana_reporting_router = APIRouter()
39
40
41 async def get_grafana_url(session: AsyncSession):
42 connector = await session.execute(select(Connectors).where(Connectors.connector_name == "Grafana"))
43 connector = connector.scalars().first()
44 return connector.connector_url
45
46
47 def calculate_unix_timestamps(time_range: TimeRange):
48 now = datetime.now()
49 if time_range.unit == "m":
50 start_time = now - timedelta(minutes=time_range.value)
51 elif time_range.unit == "h":
52 start_time = now - timedelta(hours=time_range.value)
53 elif time_range.unit == "d":
54 start_time = now - timedelta(days=time_range.value)
55
56 timestamp_from = int(time.mktime(start_time.timetuple())) * 1000
57 timestamp_to = int(time.mktime(now.timetuple())) * 1000
58
59 return timestamp_from, timestamp_to
60
61
62 def generate_panel_urls(grafana_url: str, request: GrafanaGenerateIframeLinksRequest, timestamp_from: int, timestamp_to: int):
63 panel_links: List[GrafanaLinksList] = []
64 # for panel_id in request.panel_ids:
65 panel_url = (
66 f"{grafana_url}/d-solo/{request.dashboard_uid}/{request.dashboard_title}"
67 f"?orgId={request.org_id}&from={timestamp_from}&to={timestamp_to}"
68 f"&panelId={request.panel_id}"
69 )
70 panel_links.append(GrafanaLinksList(panel_id=request.panel_id, panel_url=panel_url))
71 return panel_links
72
73
74 @grafana_reporting_router.get(
75 "/orgs",
76 response_model=GrafanaOrganizationsResponse,
77 description="Provision Grafana dashboards",
78 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
79 )
80 async def get_grafana_orgs():
81 """
82 Endpoint to provision Grafana dashboards.
83
84 Args:
85 request (DashboardProvisionRequest): The request body containing the dashboard provisioning data.
86
87 Returns:
88 GrafanaDashboardResponse: The response containing the result of the dashboard provisioning.
89 """
90 logger.info("Getting Grafana orgs")
91 orgs = await get_orgs()
92 return GrafanaOrganizationsResponse(
93 message="Organizations collected from Grafana",
94 orgs=orgs,
95 success=True,
96 )
97
98
99 @grafana_reporting_router.get(
100 "/dashboards/{org_id}",
101 response_model=GrafanaDashboardResponse,
102 description="Get Grafana dashboards for reporting",
103 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
104 )
105 async def get_grafana_dashboards(org_id: int):
106 """
107 Endpoint to get Grafana dashboards.
108
109 Args:
110 org_id (int): The ID of the organization.
111
112 Returns:
113 GrafanaDashboardResponse: The response containing the result of the dashboard provisioning.
114 """
115 dashboards = await get_dashboards(org_id=org_id)
116 return GrafanaDashboardResponse(
117 message="Dashboards collected from Grafana",
118 dashboards=dashboards,
119 success=True,
120 )
121
122
123 @grafana_reporting_router.get(
124 "/dashboard/{dashboard_uid}",
125 response_model=GrafanaDashboardDetailsResponse,
126 description="Get Grafana dashboard",
127 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
128 )
129 async def get_grafana_dashboard_details(dashboard_uid: str):
130 """
131 Endpoint to get Grafana dashboard.
132
133 Args:
134 dashboard_uid (str): The UID of the dashboard.
135
136 Returns:
137 GrafanaDashboardResponse: The response containing the result of the dashboard provisioning.
138 """
139 dashboard_details = await get_dashboard_details(dashboard_uid=dashboard_uid)
140
141 return GrafanaDashboardDetailsResponse(
142 message="Dashboard details collected from Grafana",
143 dashboard_details=dashboard_details,
144 success=True,
145 )
146
147
148 @grafana_reporting_router.get(
149 "/dashboard_panels/{dashboard_uid}",
150 response_model=GrafanaDashboardPanelsResponse,
151 description="Get Grafana dashboard panels",
152 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
153 )
154 async def get_grafana_dashboard_panels(dashboard_uid: str):
155 """
156 Endpoint to get Grafana dashboard panels.
157
158 Args:
159 dashboard_uid (str): The UID of the dashboard.
160
161 Returns:
162 GrafanaDashboardResponse: The response containing the result of the dashboard provisioning.
163 """
164 dashboard_details = await get_dashboard_details(dashboard_uid=dashboard_uid)
165 logger.info(f"Dashboard details: {dashboard_details}")
166
167 # Get the panel id and panel title from the dashboard details for each panel
168 panels = []
169 logger.info("Fetching panels from dashboard details")
170 for panel in dashboard_details["dashboard"]["panels"]:
171 if panel["type"] != "row":
172 panels.append(Panel(id=panel["id"], title=panel["title"]))
173 logger.info(f"Panels: {panels}")
174 return GrafanaDashboardPanelsResponse(
175 message="Panels collected from Grafana",
176 panels=panels,
177 success=True,
178 )
179
180
181 @grafana_reporting_router.post(
182 "/generate_iframe_links",
183 response_model=GrafanaGenerateIframeLinksResponse,
184 description="Generate Grafana dashboard iframe links",
185 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
186 )
187 async def generate_grafana_iframe_links(
188 request: GrafanaGenerateIframeLinksRequest,
189 session: AsyncSession = Depends(get_db),
190 ):
191 """
192 Endpoint to generate Grafana dashboard iframe links.
193
194 Args:
195 request (GrafanaGenerateIframeLinksRequest): The request body containing the dashboard UID and organization ID.
196
197 Returns:
198 GrafanaDashboardPanelsResponse: The response containing the result of the dashboard provisioning.
199 """
200 # get the Grafana URL from the database
201 grafana_url = await get_grafana_url(session)
202 logger.info(f"Grafana URL: {grafana_url}")
203
204 # calculate the Unix timestamps based on the current time and the provided time range
205 timestamp_from, timestamp_to = calculate_unix_timestamps(request.time_range)
206
207 # build the URL string for each panel_id
208 panel_urls = generate_panel_urls(grafana_url, request, timestamp_from, timestamp_to)
209
210 return GrafanaGenerateIframeLinksResponse(
211 message="Iframe links generated from Grafana",
212 links=panel_urls,
213 success=True,
214 )
215
216
217 @grafana_reporting_router.post(
218 "/generate-report",
219 response_model=GenerateReportResponse,
220 description="Create a new report.",
221 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
222 )
223 async def create_report(request: GenerateReportRequest, session: AsyncSession = Depends(get_db)) -> GenerateReportResponse:
224 logger.info("Generating report")
225 await is_feature_enabled("REPORTING", session)
226 return await generate_report(request, session)