Skip to content

Commit

Permalink
fix(grafana): Grafana dashboard uses contextual path and parameters a…
Browse files Browse the repository at this point in the history
…nd capability to override URL (#1557)
  • Loading branch information
andrewazores authored Feb 4, 2025
1 parent 0bdaad0 commit 6f0b1ac
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 27 deletions.
26 changes: 16 additions & 10 deletions src/app/Recordings/RecordingActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/
import { NotificationCategory, Recording, Target } from '@app/Shared/Services/api.types';
import { CapabilitiesContext } from '@app/Shared/Services/Capabilities';
import { NotificationsContext } from '@app/Shared/Services/Notifications.service';
import { ServiceContext } from '@app/Shared/Services/Services';
import { useSubscriptions } from '@app/utils/hooks/useSubscriptions';
Expand Down Expand Up @@ -42,20 +43,26 @@ export interface RecordingActionsProps {
export const RecordingActions: React.FC<RecordingActionsProps> = ({ recording, uploadFn, ...props }) => {
const { t } = useCryostatTranslation();
const context = React.useContext(ServiceContext);
const capabilities = React.useContext(CapabilitiesContext);
const notifications = React.useContext(NotificationsContext);
const [grafanaEnabled, setGrafanaEnabled] = React.useState(false);
const [isOpen, setIsOpen] = React.useState(false);

const addSubscription = useSubscriptions();

React.useEffect(() => {
addSubscription(
context.api
.grafanaDatasourceUrl()
.pipe(first())
.subscribe(() => setGrafanaEnabled(true)),
);
}, [context.api, setGrafanaEnabled, addSubscription]);
if (
capabilities.openGrafana === true ||
(typeof capabilities.openGrafana === 'string' && capabilities.openGrafana)
) {
addSubscription(
context.api
.grafanaDatasourceUrl()
.pipe(first())
.subscribe(() => setGrafanaEnabled(true)),
);
}
}, [capabilities, context.api, setGrafanaEnabled, addSubscription]);

const grafanaUpload = React.useCallback(() => {
addSubscription(
Expand All @@ -68,11 +75,10 @@ export const RecordingActions: React.FC<RecordingActionsProps> = ({ recording, u
.pipe(filter((n) => n.message.jobId === jobId)),
),
tap(() => notifications.success('Upload Success', `Recording ${recording.name} uploaded`)),
concatMap(() => context.api.grafanaDashboardUrl()),
)
.subscribe((url) => window.open(url, '_blank')),
.subscribe(() => context.api.openGrafanaDashboard(capabilities.openGrafana)),
);
}, [addSubscription, notifications, context.api, context.notificationChannel, recording, uploadFn]);
}, [capabilities, addSubscription, notifications, context.api, context.notificationChannel, recording, uploadFn]);

const handleDownloadRecording = React.useCallback(() => {
context.api.downloadRecording(recording);
Expand Down
38 changes: 21 additions & 17 deletions src/app/Shared/Services/Api.service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,8 @@ export class ApiService {
}

private testHealth() {
const getDatasourceURL: Observable<GrafanaDashboardUrlGetResponse> = this.ctx
.url('/api/v4/grafana_datasource_url')
.pipe(
concatMap((u) => fromFetch(u)),
concatMap((resp) => from(resp.json())),
);
const getDashboardURL: Observable<GrafanaDashboardUrlGetResponse> = this.ctx
.url('/api/v4/grafana_dashboard_url')
.pipe(
concatMap((u) => fromFetch(u)),
concatMap((resp) => from(resp.json())),
);
const datasourceURL: Observable<GrafanaDashboardUrlGetResponse> = this.doGet('/grafana_datasource_url', 'v4');
const dashboardURL: Observable<GrafanaDashboardUrlGetResponse> = this.doGet('/grafana_dashboard_url', 'v4');
const health: Observable<HealthGetResponse> = this.doGet('/health', 'unversioned');

health
Expand All @@ -127,7 +117,7 @@ export class ApiService {
// if both configured and available then display nothing and just retrieve the URLs
if (jsonResp.datasourceConfigured) {
if (jsonResp.datasourceAvailable) {
toFetch.push(getDatasourceURL);
toFetch.push(datasourceURL);
} else {
unavailable.push('datasource URL');
}
Expand All @@ -136,7 +126,7 @@ export class ApiService {
}
if (jsonResp.dashboardConfigured) {
if (jsonResp.dashboardAvailable) {
toFetch.push(getDashboardURL);
toFetch.push(dashboardURL);
} else {
unavailable.push('dashboard URL');
}
Expand Down Expand Up @@ -753,6 +743,18 @@ export class ApiService {
return this.grafanaDashboardUrlSubject.asObservable();
}

openGrafanaDashboard(openGrafana: string | boolean): void {
let url: Observable<string>;
if (openGrafana === true) {
url = this.grafanaDashboardUrl();
} else if (typeof openGrafana === 'string' && openGrafana) {
url = of(openGrafana);
} else {
return;
}
url.subscribe((u) => window.open(u, '_blank'));
}

doGet<T>(
path: string,
apiVersion: ApiVersion = 'v4',
Expand Down Expand Up @@ -1464,8 +1466,8 @@ export class ApiService {
return JSON.stringify(download);
}

private downloadFile(url: string, filename: string, headers = true): void {
const qs = this.ctx.headers().pipe(
private instanceSelectorHeadersAsQuery(): Observable<string> {
return this.ctx.headers().pipe(
map((headers) => {
let ns: string | undefined;
let name: string | undefined;
Expand All @@ -1485,8 +1487,10 @@ export class ApiService {
return '';
}),
);
}

const o = headers ? qs : of('');
private downloadFile(url: string, filename: string, headers = true): void {
const o = headers ? this.instanceSelectorHeadersAsQuery() : of('');
o.subscribe((q) => {
const anchor = document.createElement('a');
anchor.setAttribute('style', 'display: none; visibility: hidden;');
Expand Down
4 changes: 4 additions & 0 deletions src/app/Shared/Services/Capabilities.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ import * as React from 'react';

interface Capabilities {
fileUploads: boolean;
// false to disable the feature, true to enable using the default mechanism of
// pulling the URL from the Cryostat server, truthy string to override the URL
openGrafana: string | boolean;
}
const defaultCapabilities: Capabilities = {
fileUploads: true,
openGrafana: true,
};

const CapabilitiesContext: React.Context<Capabilities> = React.createContext(defaultCapabilities);
Expand Down

0 comments on commit 6f0b1ac

Please sign in to comment.