Skip to content

Commit 94065a8

Browse files
Merge pull request #2629 from devtron-labs/fix/grafana-datasource-url
fix: derive grafana data source URL from app details
2 parents 357bad6 + ed4a8b0 commit 94065a8

File tree

6 files changed

+134
-70
lines changed

6 files changed

+134
-70
lines changed

src/components/app/details/appDetails/AppMetrics.tsx

Lines changed: 83 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@
1515
*/
1616

1717
import React, { useState, useEffect } from 'react'
18-
import { not, Progressing, ToastManager, ToastVariantType, useAsync, useTheme } from '@devtron-labs/devtron-fe-common-lib'
18+
import {
19+
not,
20+
Progressing,
21+
ToastManager,
22+
ToastVariantType,
23+
useAsync,
24+
useTheme,
25+
} from '@devtron-labs/devtron-fe-common-lib'
1926
import { useParams, Link, NavLink } from 'react-router-dom'
2027
import moment, { Moment } from 'moment'
2128
import Tippy from '@tippyjs/react'
22-
import {
23-
getIframeSrc,
24-
ThroughputSelect,
25-
getCalendarValue,
26-
isK8sVersionValid,
27-
LatencySelect,
28-
} from './utils'
29+
import { getIframeSrc, ThroughputSelect, getCalendarValue, isK8sVersionValid, LatencySelect, AppInfo } from './utils'
2930
import {
3031
ChartTypes,
3132
AppMetricsTab,
@@ -50,7 +51,7 @@ import {
5051
ModuleNameMap,
5152
URLS,
5253
} from '../../../../config'
53-
import { isDatasourceConfigured, isDatasourceHealthy } from './appDetails.service'
54+
import { getDataSourceDetailsFromEnvironment, isDatasourceHealthy } from './appDetails.service'
5455
import { getHostURLConfiguration } from '../../../../services/service'
5556
import PrometheusErrorImage from '../../../../assets/img/ic-error-prometheus.png'
5657
import HostErrorImage from '../../../../assets/img/ic-error-hosturl.png'
@@ -59,15 +60,17 @@ import { getModuleInfo } from '../../../v2/devtronStackManager/DevtronStackManag
5960
import { ModuleStatus } from '../../../v2/devtronStackManager/DevtronStackManager.type'
6061
import { APP_METRICS_CALENDAR_INPUT_DATE_FORMAT } from './constants'
6162

62-
export const AppMetrics: React.FC<{
63-
appName: string
64-
environment
65-
podMap: Map<string, any>
66-
k8sVersion
67-
addExtraSpace: boolean
68-
}> = ({ appName, environment, podMap, k8sVersion, addExtraSpace }) => {
63+
export const AppMetrics: React.FC<
64+
{
65+
appName: string
66+
environment
67+
podMap: Map<string, any>
68+
k8sVersion
69+
addExtraSpace: boolean
70+
}
71+
> = ({ appName, podMap, k8sVersion, addExtraSpace, environment }) => {
6972
const { appTheme } = useTheme()
70-
const { appMetrics, environmentName, infraMetrics } = environment
73+
const { appMetrics, infraMetrics, environmentName } = environment
7174
const [calendar, setDateRange] = useState<{ startDate: Moment; endDate: Moment }>({
7275
startDate: moment().subtract(5, 'minute'),
7376
endDate: moment(),
@@ -76,10 +79,16 @@ export const AppMetrics: React.FC<{
7679
startDate: 'now-5m',
7780
endDate: 'now',
7881
})
79-
const [datasource, setDatasource] = useState({
82+
const [datasource, setDatasource] = useState<{
83+
isLoading: boolean
84+
isConfigured: boolean
85+
isHealthy: boolean
86+
dataSourceName: string
87+
}>({
8088
isLoading: true,
8189
isConfigured: false,
8290
isHealthy: false,
91+
dataSourceName: '',
8392
})
8493
const [focusedInput, setFocusedInput] = useState(CalendarFocusInput.StartDate)
8594
const [tab, setTab] = useState<AppMetricsTabType>(AppMetricsTab.Aggregate)
@@ -96,6 +105,8 @@ export const AppMetrics: React.FC<{
96105
throughput: '',
97106
latency: '',
98107
})
108+
109+
const { dataSourceName } = datasource
99110
const addSpace: string = addExtraSpace ? 'mb-16' : ''
100111
const pod = podMap?.values().next().value
101112
const newPodHash = pod?.networkingInfo?.labels?.['rollouts-pod-template-hash']
@@ -135,20 +146,28 @@ export const AppMetrics: React.FC<{
135146

136147
async function checkDatasource() {
137148
try {
138-
let datasourceConfiguredRes
139-
let datasourceHealthyRes
140-
let hostUrlRes
141-
hostUrlRes = await getHostURLConfiguration()
149+
const hostUrlRes = await getHostURLConfiguration()
142150
setHostURLConfig(hostUrlRes.result)
143-
datasourceConfiguredRes = await isDatasourceConfigured(environmentName)
144-
if (datasourceConfiguredRes.id) {
145-
datasourceHealthyRes = await isDatasourceHealthy(datasourceConfiguredRes.id)
151+
152+
const { dataSourceName, dataSourceId } = await getDataSourceDetailsFromEnvironment(environmentName)
153+
154+
if (dataSourceId) {
155+
const datasourceHealthyRes = await isDatasourceHealthy(dataSourceId)
156+
157+
setDatasource({
158+
isLoading: false,
159+
isConfigured: true,
160+
isHealthy: datasourceHealthyRes?.status.toLowerCase() === 'success',
161+
dataSourceName,
162+
})
163+
} else {
164+
setDatasource({
165+
isLoading: false,
166+
isConfigured: false,
167+
isHealthy: false,
168+
dataSourceName: '',
169+
})
146170
}
147-
setDatasource({
148-
isLoading: false,
149-
isConfigured: !!datasourceConfiguredRes.id,
150-
isHealthy: datasourceHealthyRes.status.toLowerCase() === 'success',
151-
})
152171
} catch (error) {
153172
setDatasource({
154173
...datasource,
@@ -170,19 +189,20 @@ export const AppMetrics: React.FC<{
170189
setCalendarValue(str)
171190
}
172191

173-
const getIframeSrcWrapper: GraphModalProps['getIframeSrcWrapper'] = (params) => getIframeSrc({
174-
...params,
175-
grafanaTheme: appTheme,
176-
})
192+
const getIframeSrcWrapper: GraphModalProps['getIframeSrcWrapper'] = (params) =>
193+
getIframeSrc({
194+
...params,
195+
grafanaTheme: appTheme,
196+
})
177197

178198
function handleStatusChange(selected): void {
179199
if (!isK8sVersionValid(k8sVersion)) {
180200
k8sVersion = DEFAULTK8SVERSION
181201
}
182-
const appInfo = {
202+
const appInfo: AppInfo = {
183203
appId,
184204
envId,
185-
environmentName,
205+
dataSourceName,
186206
newPodHash,
187207
k8sVersion,
188208
}
@@ -192,7 +212,7 @@ export const AppMetrics: React.FC<{
192212
calendarInputs,
193213
tab,
194214
isLegendRequired: true,
195-
statusCode: selected.value
215+
statusCode: selected.value,
196216
})
197217
setStatusCode(selected.value)
198218
setGraphs({
@@ -205,15 +225,21 @@ export const AppMetrics: React.FC<{
205225
if (!isK8sVersionValid(k8sVersion)) {
206226
k8sVersion = DEFAULTK8SVERSION
207227
}
208-
const appInfo = {
228+
const appInfo: AppInfo = {
209229
appId,
210230
envId,
211-
environmentName,
231+
dataSourceName,
212232
newPodHash,
213233
k8sVersion,
214234
}
215235
const latency = getIframeSrcWrapper({
216-
appInfo, chartName: ChartType.Latency, calendarInputs, tab, isLegendRequired: true, statusCode: undefined, latency: selected.value
236+
appInfo,
237+
chartName: ChartType.Latency,
238+
calendarInputs,
239+
tab,
240+
isLegendRequired: true,
241+
statusCode: undefined,
242+
latency: selected.value,
217243
})
218244
setLatency(selected.value)
219245
setGraphs({
@@ -237,18 +263,26 @@ export const AppMetrics: React.FC<{
237263
})
238264
}
239265

240-
const appInfo = {
266+
const appInfo: AppInfo = {
241267
appId,
242268
envId,
243-
environmentName,
269+
dataSourceName,
244270
newPodHash,
245271
k8sVersion,
246272
}
247273
const cpu = getIframeSrcWrapper({
248-
appInfo, chartName: ChartType.Cpu, calendarInputs, tab: newTab, isLegendRequired: true
274+
appInfo,
275+
chartName: ChartType.Cpu,
276+
calendarInputs,
277+
tab: newTab,
278+
isLegendRequired: true,
249279
})
250280
const ram = getIframeSrcWrapper({
251-
appInfo, chartName: ChartType.Ram, calendarInputs, tab: newTab, isLegendRequired: true
281+
appInfo,
282+
chartName: ChartType.Ram,
283+
calendarInputs,
284+
tab: newTab,
285+
isLegendRequired: true,
252286
})
253287
const latency = getIframeSrcWrapper({
254288
appInfo,
@@ -265,7 +299,7 @@ export const AppMetrics: React.FC<{
265299
calendarInputs,
266300
tab: newTab,
267301
isLegendRequired: true,
268-
statusCode: StatusType.Throughput
302+
statusCode: StatusType.Throughput,
269303
})
270304
setGraphs({
271305
cpu,
@@ -295,6 +329,7 @@ export const AppMetrics: React.FC<{
295329
if (
296330
!datasource.isConfigured ||
297331
!datasource.isHealthy ||
332+
!datasource.dataSourceName ||
298333
!hostURLConfig ||
299334
hostURLConfig.value !== window.location.origin
300335
) {
@@ -309,10 +344,7 @@ export const AppMetrics: React.FC<{
309344
}
310345

311346
return (
312-
<section
313-
data-testid="app-metrices-wrapper"
314-
className="app-summary bg__primary pl-24 pr-24 pb-20 w-100"
315-
>
347+
<section data-testid="app-metrices-wrapper" className="app-summary bg__primary pl-24 pr-24 pb-20 w-100">
316348
{(appMetrics || infraMetrics) && (
317349
<div className="flex" style={{ justifyContent: 'space-between', height: '68px' }}>
318350
<span className="fs-14 fw-6 cn-7 flex left mr-9">
@@ -348,7 +380,7 @@ export const AppMetrics: React.FC<{
348380
appName={appName}
349381
infraMetrics={environment.infraMetrics}
350382
appMetrics={environment.appMetrics}
351-
environmentName={environmentName}
383+
dataSourceName={dataSourceName}
352384
chartName={chartName}
353385
newPodHash={newPodHash}
354386
calendar={calendar}
@@ -514,10 +546,7 @@ const EnableAppMetrics = () => {
514546

515547
const MonitoringModuleNotInstalled = ({ addSpace }: { addSpace: string }) => {
516548
return (
517-
<div
518-
data-testid="app-metrices-wrapper"
519-
className={`bcv-1 w-100 pt-18 pb-18 pl-20 pr-20 ${addSpace}`}
520-
>
549+
<div data-testid="app-metrices-wrapper" className={`bcv-1 w-100 pt-18 pb-18 pl-20 pr-20 ${addSpace}`}>
521550
<div className="flex left w-100 lh-20">
522551
<span className="fs-14 fw-6 cv-5 flex left mr-16">
523552
<GraphIcon className="mr-8 fcv-5 icon-dim-20" />

src/components/app/details/appDetails/GraphsModal.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
ThroughputSelect,
2727
getCalendarValue,
2828
LatencySelect,
29+
AppInfo,
2930
} from './utils'
3031
import { ReactComponent as GraphIcon } from '../../../../assets/icons/ic-graph.svg'
3132
import { DEFAULTK8SVERSION } from '../../../../config'
@@ -39,14 +40,13 @@ export const ChartNames = {
3940
status: 'Status',
4041
}
4142

42-
export interface GraphModalProps {
43+
export interface GraphModalProps extends Pick<AppInfo, 'dataSourceName'> {
4344
appId: string | number
4445
envId: string | number
4546
appName: string
4647
chartName: ChartTypes
4748
infraMetrics: boolean
4849
appMetrics: boolean
49-
environmentName: string
5050
newPodHash: string
5151
calendar: { startDate: Moment; endDate: Moment }
5252
calendarInputs: { startDate: string; endDate: string }
@@ -135,10 +135,10 @@ export class GraphModal extends Component<GraphModalProps, GraphModalState> {
135135
if (!isK8sVersionValid(k8sVersion)) {
136136
k8sVersion = DEFAULTK8SVERSION
137137
}
138-
const appInfo = {
138+
const appInfo: AppInfo = {
139139
appId: this.props.appId,
140140
envId: this.props.envId,
141-
environmentName: this.props.environmentName,
141+
dataSourceName: this.props.dataSourceName,
142142
newPodHash: this.props.newPodHash,
143143
k8sVersion,
144144
}
@@ -316,10 +316,10 @@ export class GraphModal extends Component<GraphModalProps, GraphModalState> {
316316
if (!isK8sVersionValid(k8sVersion)) {
317317
k8sVersion = DEFAULTK8SVERSION
318318
}
319-
const appInfo = {
319+
const appInfo: AppInfo = {
320320
appId: this.props.appId,
321321
envId: this.props.envId,
322-
environmentName: this.props.environmentName,
322+
dataSourceName: this.props.dataSourceName,
323323
newPodHash: this.props.newPodHash,
324324
k8sVersion,
325325
}

src/components/app/details/appDetails/appDetails.service.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,36 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { ResponseType, get, trash } from '@devtron-labs/devtron-fe-common-lib'
17+
import { ResponseType, get, getUrlWithSearchParams, trash } from '@devtron-labs/devtron-fe-common-lib'
1818
import { Routes } from '../../../../config'
1919
import { fetchWithFullRoute } from '../../../../services/fetchWithFullRoute'
20-
import { ClusterConnectionResponse, DeploymentStatusDetailsResponse, ModuleConfigResponse } from './appDetails.type'
20+
import {
21+
ClusterConnectionResponse,
22+
DataSourceDetailsDTO,
23+
DataSourceDetailsQueryParams,
24+
DataSourceDetailsType,
25+
DeploymentStatusDetailsResponse,
26+
ModuleConfigResponse,
27+
} from './appDetails.type'
2128
import { AppType } from '../../../v2/appDetails/appDetails.type'
2229

23-
export function isDatasourceConfigured(envName: string) {
24-
const root = window.__ORCHESTRATOR_ROOT__.replace('/orchestrator', '')
25-
const URL = `${root}/grafana/api/datasources/id/Prometheus-${envName}`
26-
return fetchWithFullRoute(URL, 'GET')
30+
export const getDataSourceDetailsFromEnvironment = async (envName: string): Promise<DataSourceDetailsType> => {
31+
try {
32+
const {
33+
result: { name, id },
34+
} = await get<DataSourceDetailsDTO>(
35+
getUrlWithSearchParams(Routes.ENV_DATA_SOURCE_NAME, {
36+
environmentName: envName,
37+
} satisfies DataSourceDetailsQueryParams),
38+
)
39+
40+
return { dataSourceName: name, dataSourceId: id }
41+
} catch {
42+
return {
43+
dataSourceName: '',
44+
dataSourceId: null,
45+
}
46+
}
2747
}
2848

2949
export function isDatasourceHealthy(datasourceId: number | string) {

src/components/app/details/appDetails/appDetails.type.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,20 @@ export interface ModuleConfigResponse extends ResponseType {
132132
}
133133
}
134134

135+
export interface DataSourceDetailsDTO {
136+
id: number
137+
name: string
138+
}
139+
140+
export interface DataSourceDetailsQueryParams {
141+
environmentName: string
142+
}
143+
144+
export interface DataSourceDetailsType {
145+
dataSourceName: string
146+
dataSourceId: number
147+
}
148+
135149
export interface ClusterConnectionResponse extends ResponseType {
136150
result?: {
137151
clusterReachable: boolean

0 commit comments

Comments
 (0)