Skip to content

Commit

Permalink
feat(frontend): Wizard - OTLP Test connection (#3540)
Browse files Browse the repository at this point in the history
  • Loading branch information
xoscar authored Jan 18, 2024
1 parent bf61521 commit c108269
Show file tree
Hide file tree
Showing 24 changed files with 205 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const TopContainer = styled.div`
export const ButtonsContainer = styled.div`
display: flex;
justify-content: flex-end;
gap: 8px;
gap: 16px;
margin-top: 23px;
padding: 16px 0;
border-top: 1px solid ${({theme}) => theme.color.borderLight};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Button, Space, Typography} from 'antd';
import {Space, Typography} from 'antd';
import DataStoreIcon from 'components/DataStoreIcon/DataStoreIcon';
import {SupportedDataStores} from 'types/DataStore.types';
import {SupportedDataStoresToName} from 'constants/DataStore.constants';
Expand All @@ -8,7 +8,6 @@ import * as S from './DataStoreConfiguration.styled';
import TestConnectionStatus from '../TestConnectionStatus';

interface IProps {
isTestConnectionLoading: boolean;
isSubmitLoading: boolean;
isValid: boolean;
dataStoreType: SupportedDataStores;
Expand All @@ -22,50 +21,44 @@ const DataStoreConfiguration = ({
onSubmit,
onTestConnection,
isSubmitLoading,
isTestConnectionLoading,
isValid,
dataStoreType,
withColor = false,
}: IProps) => {
return (
<>
<S.TopContainer>
<Space>
<DataStoreIcon
withColor={withColor}
dataStoreType={dataStoreType ?? SupportedDataStores.JAEGER}
width="22"
height="22"
/>
}: IProps) => (
<>
<S.TopContainer>
<Space>
<DataStoreIcon
withColor={withColor}
dataStoreType={dataStoreType ?? SupportedDataStores.JAEGER}
width="22"
height="22"
/>

<Typography.Title level={2}>
{SupportedDataStoresToName[dataStoreType ?? SupportedDataStores.JAEGER]}
</Typography.Title>
</Space>
<Typography.Title level={2}>
{SupportedDataStoresToName[dataStoreType ?? SupportedDataStores.JAEGER]}
</Typography.Title>
</Space>

<S.Description>
Tracetest needs configuration information to be able to retrieve your trace from your distributed tracing
solution. Select your Tracing Backend and enter the configuration info.
</S.Description>
{dataStoreType && <DataStoreComponentFactory dataStoreType={dataStoreType} />}
</S.TopContainer>
<S.ButtonsContainer>
<TestConnectionStatus />
<Button loading={isTestConnectionLoading} type="primary" ghost onClick={onTestConnection}>
Test Connection
</Button>
<AllowButton
operation={Operation.Configure}
disabled={!isValid}
loading={isSubmitLoading}
type="primary"
onClick={onSubmit}
>
Save
</AllowButton>
</S.ButtonsContainer>
</>
);
};
<S.Description>
Tracetest needs configuration information to be able to retrieve your trace from your distributed tracing
solution. Select your Tracing Backend and enter the configuration info.
</S.Description>
{dataStoreType && <DataStoreComponentFactory dataStoreType={dataStoreType} />}
</S.TopContainer>
<S.ButtonsContainer>
<TestConnectionStatus onTestConnection={onTestConnection} />
<AllowButton
operation={Operation.Configure}
disabled={!isValid}
loading={isSubmitLoading}
type="primary"
onClick={onSubmit}
>
Save
</AllowButton>
</S.ButtonsContainer>
</>
);

export default DataStoreConfiguration;
12 changes: 1 addition & 11 deletions web/src/components/Settings/DataStore/DataStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,7 @@ import * as S from './DataStore.styled';

const DataStore = () => {
const {dataStoreConfig} = useSettingsValues();
const {
isLoading,
isFormValid,
onIsFormValid,
onSaveConfig,
isTestConnectionLoading,
onTestConnection,
resetTestConnection,
} = useDataStore();
const {isLoading, isFormValid, onIsFormValid, onSaveConfig, onTestConnection} = useDataStore();
const [form] = Form.useForm<TDraftDataStore>();

const handleOnSubmit = useCallback(
Expand All @@ -39,11 +31,9 @@ const DataStore = () => {
dataStoreConfig={dataStoreConfig}
onSubmit={handleOnSubmit}
onTestConnection={handleTestConnection}
isTestConnectionLoading={isTestConnectionLoading}
isLoading={isLoading}
isFormValid={isFormValid}
onIsFormValid={onIsFormValid}
resetTestConnection={resetTestConnection}
/>
</S.FormContainer>
</S.Wrapper>
Expand Down
9 changes: 0 additions & 9 deletions web/src/components/Settings/DataStoreForm/DataStoreForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ interface IProps {
onSubmit(values: TDraftDataStore): Promise<void>;
onIsFormValid(isValid: boolean): void;
onTestConnection(): void;
isTestConnectionLoading: boolean;
resetTestConnection(): void;
isLoading: boolean;
isFormValid: boolean;
}
Expand All @@ -27,8 +25,6 @@ const DataStoreForm = ({
dataStoreConfig,
onIsFormValid,
onTestConnection,
resetTestConnection,
isTestConnectionLoading,
isLoading,
isFormValid,
}: IProps) => {
Expand All @@ -45,10 +41,6 @@ const DataStoreForm = ({
});
}, [dataStoreType, form, initialValues.dataStore]);

useEffect(() => {
resetTestConnection();
}, [dataStoreType]);

const onValidation = useCallback(
async (_: any, draft: TDraftDataStore) => {
try {
Expand Down Expand Up @@ -80,7 +72,6 @@ const DataStoreForm = ({
onSubmit={() => form.submit()}
onTestConnection={onTestConnection}
isValid={isFormValid}
isTestConnectionLoading={isTestConnectionLoading}
isSubmitLoading={isLoading}
dataStoreType={dataStoreType ?? SupportedDataStores.JAEGER}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {CheckCircleFilled, InfoCircleFilled, LoadingOutlined, MinusCircleFilled} from '@ant-design/icons';
import {Typography} from 'antd';
import styled from 'styled-components';

export const StatusContainer = styled.div`
Expand All @@ -22,3 +23,20 @@ export const IconInfo = styled(InfoCircleFilled)`
export const LoadingIcon = styled(LoadingOutlined)`
color: ${({theme}) => theme.color.primary};
`;

export const StatusText = styled(Typography.Paragraph).attrs({
type: 'secondary',
})`
&& {
font-weight: 600;
margin: 0;
}
`;

export const SpanCountTest = styled(Typography.Text).attrs({
type: 'secondary',
})`
&& {
font-size: ${({theme}) => theme.size.sm};
}
`;
56 changes: 30 additions & 26 deletions web/src/components/TestConnectionStatus/TestConnectionStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import {useMemo} from 'react';
import {TDraftDataStore} from 'types/DataStore.types';
import DataStoreService from 'services/DataStore.service';
import {useDataStore} from 'providers/DataStore/DataStore.provider';
import {Form, Typography} from 'antd';
import OTLPTestConnectionResponse from 'models/OTLPTestConnectionResponse.model';
import Date from 'utils/Date';
import {Button} from 'antd';
import * as S from './TestConnectionStatus.styled';

export type TConnectionStatus = 'loading' | 'success' | 'error' | 'idle';
import useTestConnectionStatus, {TConnectionStatus} from './hooks/useTestConnnectionStatus';

const Icon = ({status}: {status: TConnectionStatus}) => {
switch (status) {
Expand All @@ -21,41 +18,48 @@ const Icon = ({status}: {status: TConnectionStatus}) => {
}
};

const getText = (status: TConnectionStatus, shouldTestConnection: boolean) => {
const getText = (status: TConnectionStatus, {spanCount, lastSpanTimestamp} = OTLPTestConnectionResponse()) => {
switch (status) {
case 'loading':
return shouldTestConnection ? 'Connecting to Data Store' : 'Waiting for incoming traces';
return 'Waiting for incoming traces';
case 'success':
return shouldTestConnection ? 'Successful Connection' : 'We received your traces';
return (
<>
We received your traces
<br />
<S.SpanCountTest>
<i>
{spanCount} spans, {Date.getTimeAgo(lastSpanTimestamp)}
</i>
</S.SpanCountTest>
</>
);
case 'error':
return shouldTestConnection ? 'Connection Failed' : 'We could not receive your traces';
return 'We could not receive your traces';
case 'idle':
default:
return 'Waiting for Test Connection';
}
};

const TestConnectionStatus = () => {
const {isTestConnectionLoading, testConnectionResponse} = useDataStore();
const form = Form.useFormInstance<TDraftDataStore>();

const shouldTest = useMemo(() => DataStoreService.shouldTestConnection(form.getFieldsValue()), [form]);

const status = useMemo<TConnectionStatus>(() => {
if (isTestConnectionLoading) return 'loading';
if (!testConnectionResponse) return 'idle';
interface IProps {
onTestConnection(): void;
}

return testConnectionResponse.allPassed ? 'success' : 'error';
}, [isTestConnectionLoading, testConnectionResponse]);
const TestConnectionStatus = ({onTestConnection}: IProps) => {
const {status, isOtlpBased, isLoading, otlpResponse} = useTestConnectionStatus();

const text = getText(status, shouldTest);
if (!isOtlpBased)
return (
<Button loading={isLoading} type="primary" ghost onClick={onTestConnection}>
Test Connection
</Button>
);

return (
<S.StatusContainer>
<Icon status={status} />
<Typography.Text type="secondary">
<b>{text}</b>
</Typography.Text>
<S.StatusText>{getText(status, otlpResponse)}</S.StatusText>
</S.StatusContainer>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {Form} from 'antd';
import {useEffect, useMemo} from 'react';
import {useDataStore} from 'providers/DataStore/DataStore.provider';
import {TDraftDataStore} from 'types/DataStore.types';
import TracetestAPI from 'redux/apis/Tracetest/Tracetest.api';
import DataStoreService from 'services/DataStore.service';

export type TConnectionStatus = 'loading' | 'success' | 'error' | 'idle';

const useTestConnectionStatus = () => {
// had to do this at this level because of this issue
// https://github.com/reduxjs/redux-toolkit/issues/2055
const {useLazyTestOtlpConnectionQuery, useResetTestOtlpConnectionMutation} = TracetestAPI.instance;
const [resetOtlpCount] = useResetTestOtlpConnectionMutation();

const {isTestConnectionLoading, resetTestConnection} = useDataStore();
const form = Form.useFormInstance<TDraftDataStore>();
const [testOtlpConnection, {isLoading, data: otlpResponse, isError}] = useLazyTestOtlpConnectionQuery({
pollingInterval: 1000,
});

const status = useMemo<TConnectionStatus>(() => {
if (isTestConnectionLoading || !otlpResponse?.spanCount) return 'loading';
if (!otlpResponse) return 'idle';
if (isError) return 'error';

return 'success';
}, [isError, isTestConnectionLoading, otlpResponse]);

// listens to all form changes
const data = Form.useWatch([], form);
const isOtlpBased = useMemo(() => DataStoreService.getIsOtlpBased(form.getFieldsValue()), [data]);

Check warning on line 32 in web/src/components/TestConnectionStatus/hooks/useTestConnnectionStatus.ts

View workflow job for this annotation

GitHub Actions / WebUI unit tests

React Hook useMemo has a missing dependency: 'form'. Either include it or remove the dependency array

useEffect(() => {
if (isOtlpBased) testOtlpConnection(undefined);
}, [isOtlpBased]);

Check warning on line 36 in web/src/components/TestConnectionStatus/hooks/useTestConnnectionStatus.ts

View workflow job for this annotation

GitHub Actions / WebUI unit tests

React Hook useEffect has a missing dependency: 'testOtlpConnection'. Either include it or remove the dependency array

useEffect(() => {
return () => {
resetOtlpCount(undefined);
resetTestConnection();
};
}, []);

Check warning on line 43 in web/src/components/TestConnectionStatus/hooks/useTestConnnectionStatus.ts

View workflow job for this annotation

GitHub Actions / WebUI unit tests

React Hook useEffect has missing dependencies: 'resetOtlpCount' and 'resetTestConnection'. Either include them or remove the dependency array

return {status, isOtlpBased, otlpResponse, isLoading: isLoading || isTestConnectionLoading};
};

export default useTestConnectionStatus;
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface IProps {
}

const Configuration = ({dataStore, onBack}: IProps) => {
const {isLoading, isFormValid, onIsFormValid, onSaveConfig, isTestConnectionLoading, onTestConnection} =
const {isLoading, isFormValid, onIsFormValid, onSaveConfig, onTestConnection} =
useDataStore();
const [form] = Form.useForm<TDraftDataStore>();

Expand Down Expand Up @@ -76,7 +76,6 @@ const Configuration = ({dataStore, onBack}: IProps) => {
isSubmitLoading={isLoading}
isValid={isFormValid}
withColor
isTestConnectionLoading={isTestConnectionLoading}
/>
</Form>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {useCallback, useEffect, useState} from 'react';
import {useCallback, useState} from 'react';
import {useSettingsValues} from 'providers/SettingsValues/SettingsValues.provider';
import {useDataStore} from 'providers/DataStore/DataStore.provider';
import DataStore, {fromType} from 'models/DataStore.model';
import Selector from './Selector';
import Configuration from './Configuration';
Expand All @@ -9,7 +8,6 @@ const TracingBackend = () => {
const {
dataStoreConfig: {defaultDataStore},
} = useSettingsValues();
const {resetTestConnection} = useDataStore();
const [selectedDataStore, setSelectedDataStore] = useState<DataStore | undefined>(defaultDataStore);

const handleOnSelect = useCallback(
Expand All @@ -19,10 +17,6 @@ const TracingBackend = () => {
[defaultDataStore]
);

useEffect(() => {
resetTestConnection();
}, [selectedDataStore?.type]);

if (!selectedDataStore) return <Selector onSelect={handleOnSelect} />;

return <Configuration dataStore={selectedDataStore} onBack={() => setSelectedDataStore(undefined)} />;
Expand Down
21 changes: 21 additions & 0 deletions web/src/models/OTLPTestConnectionResponse.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {Model, TConfigSchemas} from 'types/Common.types';

export type TRawOTLPTestConnectionResponse = TConfigSchemas['OTLPTestConnectionResponse'];
type OTLPTestConnectionResponse = Model<TRawOTLPTestConnectionResponse, {}>;

const defaultOTLPTestConnectionResponse: TRawOTLPTestConnectionResponse = {
spanCount: 0,
lastSpanTimestamp: '',
};

function OTLPTestConnectionResponse({
spanCount = 0,
lastSpanTimestamp = '',
} = defaultOTLPTestConnectionResponse): OTLPTestConnectionResponse {
return {
spanCount,
lastSpanTimestamp,
};
}

export default OTLPTestConnectionResponse;
Loading

0 comments on commit c108269

Please sign in to comment.