mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Synthetics] Monitor details panel (#134814)
Co-authored-by: Abdul Zahid <awahab07@yahoo.com>
This commit is contained in:
parent
d11c0be465
commit
0ee2ae074e
20 changed files with 421 additions and 43 deletions
|
@ -9,7 +9,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
|||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { ESSearchResponse } from '@kbn/core/types/elasticsearch';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { IInspectorInfo, isCompleteResponse } from '@kbn/data-plugin/common';
|
||||
import { IInspectorInfo, isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
||||
import { FETCH_STATUS, useFetcher } from './use_fetcher';
|
||||
import { useInspectorContext } from '../context/inspector/use_inspector_context';
|
||||
import { getInspectResponse } from '../../common/utils/get_inspect_response';
|
||||
|
@ -69,6 +69,34 @@ export const useEsSearch = <DocumentSource extends unknown, TParams extends esty
|
|||
search$.unsubscribe();
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
if (isErrorResponse(err)) {
|
||||
console.error(err);
|
||||
if (addInspectorRequest) {
|
||||
addInspectorRequest({
|
||||
data: {
|
||||
_inspect: [
|
||||
getInspectResponse({
|
||||
startTime,
|
||||
esRequestParams: params,
|
||||
esResponse: null,
|
||||
esError: { originalError: err, name: err.name, message: err.message },
|
||||
esRequestStatus: 2,
|
||||
operationName: name,
|
||||
kibanaRequest: {
|
||||
route: {
|
||||
path: '/internal/bsearch',
|
||||
method: 'POST',
|
||||
},
|
||||
} as any,
|
||||
}),
|
||||
],
|
||||
},
|
||||
status: FETCH_STATUS.SUCCESS,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
|
||||
export const CLIENT_DEFAULTS = {
|
||||
ABSOLUTE_DATE_RANGE_START: 0,
|
||||
// 15 minutes
|
||||
|
@ -43,3 +45,17 @@ export const CLIENT_DEFAULTS = {
|
|||
};
|
||||
|
||||
export const EXCLUDE_RUN_ONCE_FILTER = { bool: { must_not: { exists: { field: 'run_once' } } } };
|
||||
export const SUMMARY_FILTER = {
|
||||
exists: {
|
||||
field: 'summary',
|
||||
},
|
||||
};
|
||||
|
||||
export const getTimeSpanFilter = () => ({
|
||||
range: {
|
||||
'monitor.timespan': {
|
||||
lte: moment().toISOString(),
|
||||
gte: moment().subtract(5, 'minutes').toISOString(),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useEsSearch } from '@kbn/observability-plugin/public';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useMemo } from 'react';
|
||||
import { Ping } from '../../../../../../common/runtime_types';
|
||||
import {
|
||||
EXCLUDE_RUN_ONCE_FILTER,
|
||||
getTimeSpanFilter,
|
||||
SUMMARY_FILTER,
|
||||
} from '../../../../../../common/constants/client_defaults';
|
||||
import { useSyntheticsRefreshContext } from '../../../contexts/synthetics_refresh_context';
|
||||
import { SYNTHETICS_INDEX_PATTERN, UNNAMED_LOCATION } from '../../../../../../common/constants';
|
||||
|
||||
export function useStatusByLocation() {
|
||||
const { lastRefresh } = useSyntheticsRefreshContext();
|
||||
|
||||
const { monitorId } = useParams<{ monitorId: string }>();
|
||||
|
||||
const { data, loading } = useEsSearch(
|
||||
{
|
||||
index: SYNTHETICS_INDEX_PATTERN,
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
SUMMARY_FILTER,
|
||||
EXCLUDE_RUN_ONCE_FILTER,
|
||||
getTimeSpanFilter(),
|
||||
{
|
||||
term: {
|
||||
config_id: monitorId,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
sort: [{ '@timestamp': 'desc' }],
|
||||
aggs: {
|
||||
locations: {
|
||||
terms: {
|
||||
field: 'observer.geo.name',
|
||||
missing: UNNAMED_LOCATION,
|
||||
size: 1000,
|
||||
},
|
||||
aggs: {
|
||||
summary: {
|
||||
top_hits: {
|
||||
size: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[lastRefresh, monitorId],
|
||||
{ name: 'getMonitorStatusByLocation' }
|
||||
);
|
||||
|
||||
return useMemo(() => {
|
||||
const locations = (data?.aggregations?.locations.buckets ?? []).map((loc) => {
|
||||
return loc.summary.hits.hits?.[0]._source as Ping;
|
||||
});
|
||||
|
||||
return { locations, loading };
|
||||
}, [data, loading]);
|
||||
}
|
|
@ -5,14 +5,23 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { selectMonitorStatus } from '../../state/monitor_summary';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { getSyntheticsMonitorAction, selectMonitorStatus } from '../../state/monitor_summary';
|
||||
import { useMonitorListBreadcrumbs } from '../monitors_page/hooks/use_breadcrumbs';
|
||||
export const MonitorSummaryPage = () => {
|
||||
const { data } = useSelector(selectMonitorStatus);
|
||||
|
||||
useMonitorListBreadcrumbs([{ text: data?.monitor.name ?? '' }]);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const { monitorId } = useParams<{ monitorId: string }>();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getSyntheticsMonitorAction.get(monitorId));
|
||||
}, [dispatch, monitorId]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ export const MonitorSummaryTabs = () => {
|
|||
return (
|
||||
<EuiTabbedContent
|
||||
tabs={tabs}
|
||||
initialSelectedTab={tabs[1]}
|
||||
initialSelectedTab={tabs[0]}
|
||||
autoFocus="selected"
|
||||
onTabClick={(tab) => {}}
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { EuiBadge, EuiBadgeGroup, EuiIcon, EuiLoadingSpinner } from '@elastic/eui';
|
||||
import { useStatusByLocation } from '../hooks/use_status_by_location';
|
||||
|
||||
export const LocationsStatus = () => {
|
||||
const { locations, loading } = useStatusByLocation();
|
||||
|
||||
if (loading) {
|
||||
return <EuiLoadingSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiBadgeGroup>
|
||||
{locations.map((loc) => (
|
||||
<EuiBadge
|
||||
iconType={() => (
|
||||
<EuiIcon type="dot" color={(loc.summary?.down ?? 0) > 0 ? 'danger' : 'success'} />
|
||||
)}
|
||||
color="hollow"
|
||||
>
|
||||
{loc.observer?.geo?.name}
|
||||
</EuiBadge>
|
||||
))}
|
||||
</EuiBadgeGroup>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiDescriptionList,
|
||||
EuiDescriptionListTitle,
|
||||
EuiDescriptionListDescription,
|
||||
EuiBadge,
|
||||
EuiSpacer,
|
||||
EuiLink,
|
||||
EuiLoadingSpinner,
|
||||
} from '@elastic/eui';
|
||||
import { capitalize } from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { MonitorTags } from './monitor_tags';
|
||||
import { MonitorEnabled } from '../../monitors_page/management/monitor_list_table/monitor_enabled';
|
||||
import { LocationsStatus } from './locations_status';
|
||||
import {
|
||||
getSyntheticsMonitorAction,
|
||||
selectMonitorStatus,
|
||||
syntheticsMonitorSelector,
|
||||
} from '../../../state/monitor_summary';
|
||||
import { ConfigKey } from '../../../../../../common/runtime_types';
|
||||
|
||||
export const MonitorDetailsPanel = () => {
|
||||
const { data } = useSelector(selectMonitorStatus);
|
||||
|
||||
const { monitorId } = useParams<{ monitorId: string }>();
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const { data: monitor, loading } = useSelector(syntheticsMonitorSelector);
|
||||
|
||||
if (!data) {
|
||||
return <EuiLoadingSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiSpacer />
|
||||
<EuiDescriptionList type="responsiveColumn" style={{ maxWidth: '400px' }}>
|
||||
<EuiDescriptionListTitle>{ENABLED_LABEL}</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
{monitor && (
|
||||
<MonitorEnabled
|
||||
initialLoading={loading}
|
||||
id={monitorId}
|
||||
monitor={monitor}
|
||||
reloadPage={() => {
|
||||
dispatch(getSyntheticsMonitorAction.get(monitorId));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</EuiDescriptionListDescription>
|
||||
<EuiDescriptionListTitle>{MONITOR_TYPE_LABEL}</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
<EuiBadge>{capitalize(data.monitor.type)}</EuiBadge>
|
||||
</EuiDescriptionListDescription>
|
||||
<EuiDescriptionListTitle>{FREQUENCY_LABEL}</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>Every 10 mins</EuiDescriptionListDescription>
|
||||
<EuiDescriptionListTitle>{LOCATIONS_LABEL}</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
<LocationsStatus />
|
||||
</EuiDescriptionListDescription>
|
||||
<EuiDescriptionListTitle>{URL_LABEL}</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
<EuiLink href={data.url?.full} external>
|
||||
{data.url?.full}
|
||||
</EuiLink>
|
||||
</EuiDescriptionListDescription>
|
||||
<EuiDescriptionListTitle>{TAGS_LABEL}</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
{monitor && <MonitorTags tags={monitor[ConfigKey.TAGS]} />}
|
||||
</EuiDescriptionListDescription>
|
||||
</EuiDescriptionList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const FREQUENCY_LABEL = i18n.translate('xpack.synthetics.management.monitorList.frequency', {
|
||||
defaultMessage: 'Frequency',
|
||||
});
|
||||
const LOCATIONS_LABEL = i18n.translate('xpack.synthetics.management.monitorList.locations', {
|
||||
defaultMessage: 'Locations',
|
||||
});
|
||||
|
||||
const URL_LABEL = i18n.translate('xpack.synthetics.management.monitorList.url', {
|
||||
defaultMessage: 'URL',
|
||||
});
|
||||
|
||||
const TAGS_LABEL = i18n.translate('xpack.synthetics.management.monitorList.tags', {
|
||||
defaultMessage: 'Tags',
|
||||
});
|
||||
|
||||
const ENABLED_LABEL = i18n.translate('xpack.synthetics.detailsPanel.monitorDetails.enabled', {
|
||||
defaultMessage: 'Enabled',
|
||||
});
|
||||
|
||||
const MONITOR_TYPE_LABEL = i18n.translate(
|
||||
'xpack.synthetics.detailsPanel.monitorDetails.monitorType',
|
||||
{
|
||||
defaultMessage: 'Monitor type',
|
||||
}
|
||||
);
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiBadge, EuiBadgeGroup } from '@elastic/eui';
|
||||
|
||||
export const MonitorTags = ({ tags }: { tags: string[] }) => {
|
||||
return (
|
||||
<EuiBadgeGroup>
|
||||
{tags.map((tag) => (
|
||||
<EuiBadge color="hollow">{tag}</EuiBadge>
|
||||
))}
|
||||
</EuiBadgeGroup>
|
||||
);
|
||||
};
|
|
@ -5,9 +5,23 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiText } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { EuiTitle, EuiPanel } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { MonitorDetailsPanel } from './monitor_details_panel';
|
||||
|
||||
export const SummaryTabContent = () => {
|
||||
return <EuiText>Monitor summary tab content</EuiText>;
|
||||
return (
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s">
|
||||
<h3>{MONITOR_DETAILS_LABEL}</h3>
|
||||
</EuiTitle>
|
||||
<MonitorDetailsPanel />
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
||||
|
||||
const MONITOR_DETAILS_LABEL = i18n.translate('xpack.synthetics.detailsPanel.monitorDetails', {
|
||||
defaultMessage: 'Monitor details',
|
||||
});
|
||||
|
|
|
@ -132,12 +132,7 @@ export function getMonitorListColumns({
|
|||
defaultMessage: 'Enabled',
|
||||
}),
|
||||
render: (_enabled: boolean, monitor: EncryptedSyntheticsSavedMonitor) => (
|
||||
<MonitorEnabled
|
||||
id={monitor.id}
|
||||
monitor={monitor}
|
||||
isDisabled={!canEditSynthetics}
|
||||
reloadPage={reloadPage}
|
||||
/>
|
||||
<MonitorEnabled id={monitor.id} monitor={monitor} reloadPage={reloadPage} />
|
||||
),
|
||||
},
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@ import React, { useEffect, useState } from 'react';
|
|||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { FETCH_STATUS, useFetcher } from '@kbn/observability-plugin/public';
|
||||
|
||||
import { useCanEditSynthetics } from '../../../../../../hooks/use_capabilities';
|
||||
import { ConfigKey, EncryptedSyntheticsMonitor } from '../../../../../../../common/runtime_types';
|
||||
import { fetchUpsertMonitor } from '../../../../state';
|
||||
|
||||
|
@ -19,10 +20,12 @@ interface Props {
|
|||
id: string;
|
||||
monitor: EncryptedSyntheticsMonitor;
|
||||
reloadPage: () => void;
|
||||
isDisabled?: boolean;
|
||||
initialLoading?: boolean;
|
||||
}
|
||||
|
||||
export const MonitorEnabled = ({ id, monitor, reloadPage, isDisabled }: Props) => {
|
||||
export const MonitorEnabled = ({ id, monitor, reloadPage, initialLoading }: Props) => {
|
||||
const isDisabled = !useCanEditSynthetics();
|
||||
|
||||
const [isEnabled, setIsEnabled] = useState<boolean | null>(null);
|
||||
|
||||
const { notifications } = useKibana();
|
||||
|
@ -69,7 +72,7 @@ export const MonitorEnabled = ({ id, monitor, reloadPage, isDisabled }: Props) =
|
|||
|
||||
return (
|
||||
<>
|
||||
{isLoading ? (
|
||||
{isLoading || initialLoading ? (
|
||||
<EuiLoadingSpinner size="m" />
|
||||
) : (
|
||||
<EuiSwitch
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
import { Ping } from '../../../../../common/runtime_types';
|
||||
import { Ping, SyntheticsMonitor } from '../../../../../common/runtime_types';
|
||||
import { QueryParams } from './api';
|
||||
import { createAsyncAction } from '../utils/actions';
|
||||
|
||||
|
@ -15,3 +15,7 @@ export const setMonitorSummaryLocationAction = createAction<string>(
|
|||
);
|
||||
|
||||
export const getMonitorStatusAction = createAsyncAction<QueryParams, Ping>('[MONITOR SUMMARY] GET');
|
||||
|
||||
export const getSyntheticsMonitorAction = createAsyncAction<string, SyntheticsMonitor>(
|
||||
'fetchSyntheticsMonitorAction'
|
||||
);
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { SavedObject } from '@kbn/core/types';
|
||||
import { apiService } from '../../../../utils/api_service';
|
||||
import { Ping } from '../../../../../common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '../../../../../common/constants';
|
||||
import { Ping, SyntheticsMonitor } from '../../../../../common/runtime_types';
|
||||
import { API_URLS, SYNTHETICS_API_URLS } from '../../../../../common/constants';
|
||||
|
||||
export interface QueryParams {
|
||||
monitorId: string;
|
||||
|
@ -18,3 +19,11 @@ export interface QueryParams {
|
|||
export const fetchMonitorStatus = async (params: QueryParams): Promise<Ping> => {
|
||||
return await apiService.get(SYNTHETICS_API_URLS.MONITOR_STATUS, { ...params });
|
||||
};
|
||||
|
||||
export const fetchSyntheticsMonitor = async (monitorId: string): Promise<SyntheticsMonitor> => {
|
||||
const { attributes } = (await apiService.get(
|
||||
`${API_URLS.SYNTHETICS_MONITORS}/${monitorId}`
|
||||
)) as SavedObject<SyntheticsMonitor>;
|
||||
|
||||
return attributes;
|
||||
};
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
import { takeLeading } from 'redux-saga/effects';
|
||||
import { fetchEffectFactory } from '../utils/fetch_effect';
|
||||
import { getMonitorStatusAction } from './actions';
|
||||
import { fetchMonitorStatus } from './api';
|
||||
import { getMonitorStatusAction, getSyntheticsMonitorAction } from './actions';
|
||||
import { fetchMonitorStatus, fetchSyntheticsMonitor } from './api';
|
||||
|
||||
export function* fetchMonitorStatusEffect() {
|
||||
yield takeLeading(
|
||||
|
@ -20,3 +20,14 @@ export function* fetchMonitorStatusEffect() {
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function* fetchSyntheticsMonitorEffect() {
|
||||
yield takeLeading(
|
||||
getSyntheticsMonitorAction.get,
|
||||
fetchEffectFactory(
|
||||
fetchSyntheticsMonitor,
|
||||
getSyntheticsMonitorAction.success,
|
||||
getSyntheticsMonitorAction.fail
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,3 +16,5 @@ export const selectSelectedLocationId = createSelector(
|
|||
);
|
||||
|
||||
export const selectMonitorStatus = createSelector(getState, (state) => state);
|
||||
|
||||
export const syntheticsMonitorSelector = (state: SyntheticsAppState) => state.syntheticsMonitor;
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public';
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
import { SyntheticsMonitor } from '../../../../../common/runtime_types';
|
||||
import { getSyntheticsMonitorAction } from './actions';
|
||||
|
||||
export interface SyntheticsMonitorState {
|
||||
data: SyntheticsMonitor | null;
|
||||
loading: boolean;
|
||||
error: IHttpFetchError<ResponseErrorBody> | null;
|
||||
}
|
||||
|
||||
const initialState: SyntheticsMonitorState = {
|
||||
data: null,
|
||||
loading: false,
|
||||
error: null,
|
||||
};
|
||||
|
||||
export const syntheticsMonitorReducer = createReducer(initialState, (builder) => {
|
||||
builder
|
||||
.addCase(getSyntheticsMonitorAction.get, (state) => {
|
||||
state.loading = true;
|
||||
})
|
||||
.addCase(getSyntheticsMonitorAction.success, (state, action) => {
|
||||
state.data = action.payload;
|
||||
state.loading = false;
|
||||
})
|
||||
.addCase(getSyntheticsMonitorAction.fail, (state, action) => {
|
||||
state.error = action.payload as IHttpFetchError<ResponseErrorBody>;
|
||||
state.loading = false;
|
||||
});
|
||||
});
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { all, fork } from 'redux-saga/effects';
|
||||
import { fetchMonitorStatusEffect } from './monitor_summary';
|
||||
import { fetchMonitorStatusEffect, fetchSyntheticsMonitorEffect } from './monitor_summary';
|
||||
import { fetchIndexStatusEffect } from './index_status';
|
||||
import { fetchSyntheticsEnablementEffect } from './synthetics_enablement';
|
||||
import { fetchMonitorListEffect } from './monitor_list';
|
||||
|
@ -19,5 +19,6 @@ export const rootEffect = function* root(): Generator {
|
|||
fork(fetchServiceLocationsEffect),
|
||||
fork(fetchMonitorListEffect),
|
||||
fork(fetchMonitorStatusEffect),
|
||||
fork(fetchSyntheticsMonitorEffect),
|
||||
]);
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { combineReducers } from '@reduxjs/toolkit';
|
||||
|
||||
import { syntheticsMonitorReducer } from './monitor_summary/synthetics_montior_reducer';
|
||||
import { monitorStatusReducer } from './monitor_summary';
|
||||
import { uiReducer } from './ui';
|
||||
import { indexStatusReducer } from './index_status';
|
||||
|
@ -21,6 +22,7 @@ export const rootReducer = combineReducers({
|
|||
monitorList: monitorListReducer,
|
||||
serviceLocations: serviceLocationsReducer,
|
||||
monitorStatus: monitorStatusReducer,
|
||||
syntheticsMonitor: syntheticsMonitorReducer,
|
||||
});
|
||||
|
||||
export type SyntheticsAppState = ReturnType<typeof rootReducer>;
|
||||
|
|
|
@ -84,4 +84,9 @@ export const mockState: SyntheticsAppState = {
|
|||
error: null,
|
||||
selectedLocationId: null,
|
||||
},
|
||||
syntheticsMonitor: {
|
||||
data: null,
|
||||
loading: false,
|
||||
error: null,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -55,8 +55,11 @@ export class ServiceAPIClient {
|
|||
this.server = server;
|
||||
}
|
||||
|
||||
getHttpsAgent() {
|
||||
getHttpsAgent(url: string) {
|
||||
const config = this.config;
|
||||
if (url !== this.config.devUrl && this.authorization && this.server.isDev) {
|
||||
return;
|
||||
}
|
||||
if (config.tls && config.tls.certificate && config.tls.key) {
|
||||
const tlsConfig = new SslConfig(config.tls);
|
||||
|
||||
|
@ -92,29 +95,31 @@ export class ServiceAPIClient {
|
|||
return { allowed: true, signupUrl: null };
|
||||
}
|
||||
|
||||
const httpsAgent = this.getHttpsAgent();
|
||||
|
||||
if (this.locations.length > 0 && httpsAgent) {
|
||||
if (this.locations.length > 0) {
|
||||
// get a url from a random location
|
||||
const url = this.locations[Math.floor(Math.random() * this.locations.length)].url;
|
||||
|
||||
try {
|
||||
const { data } = await axios({
|
||||
method: 'GET',
|
||||
url: url + '/allowed',
|
||||
headers:
|
||||
process.env.NODE_ENV !== 'production' && this.authorization
|
||||
? {
|
||||
Authorization: this.authorization,
|
||||
}
|
||||
: undefined,
|
||||
httpsAgent,
|
||||
});
|
||||
const httpsAgent = this.getHttpsAgent(url);
|
||||
|
||||
const { allowed, signupUrl } = data;
|
||||
return { allowed, signupUrl };
|
||||
} catch (e) {
|
||||
this.logger.error(e);
|
||||
if (httpsAgent) {
|
||||
try {
|
||||
const { data } = await axios({
|
||||
method: 'GET',
|
||||
url: url + '/allowed',
|
||||
headers:
|
||||
process.env.NODE_ENV !== 'production' && this.authorization
|
||||
? {
|
||||
Authorization: this.authorization,
|
||||
}
|
||||
: undefined,
|
||||
httpsAgent,
|
||||
});
|
||||
|
||||
const { allowed, signupUrl } = data;
|
||||
return { allowed, signupUrl };
|
||||
} catch (e) {
|
||||
this.logger.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +156,7 @@ export class ServiceAPIClient {
|
|||
Authorization: this.authorization,
|
||||
}
|
||||
: undefined,
|
||||
httpsAgent: this.getHttpsAgent(),
|
||||
httpsAgent: this.getHttpsAgent(url),
|
||||
});
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue