Skip to content

Commit

Permalink
feat(frontend): add analyzer errors by attribute (#2846)
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgeepc authored Jul 4, 2023
1 parent 57ef16e commit 6f8135a
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {ExclamationCircleFilled} from '@ant-design/icons';
import {Typography} from 'antd';
import styled from 'styled-components';

export const Container = styled.div`
align-items: center;
display: flex;
gap: 4px;
`;

export const ContentContainer = styled.div`
overflow-wrap: break-word;
width: 270px;
`;

export const ErrorIcon = styled(ExclamationCircleFilled)`
color: ${({theme}) => theme.color.error};
`;

export const List = styled.ul`
padding-inline-start: 20px;
`;

export const RuleContainer = styled.div`
margin-bottom: 8px;
`;

export const Text = styled(Typography.Text)``;

export const Title = styled(Typography.Title)`
&& {
margin-bottom: 0;
}
`;
22 changes: 22 additions & 0 deletions web/src/components/AnalyzerErrorsPopover/AnalyzerErrorsPopover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {Popover} from 'antd';
import {TAnalyzerError} from 'types/TestRun.types';
import * as S from './AnalyzerErrorsPopover.styled';
import Content from './Content';

interface IProps {
errors: TAnalyzerError[];
}

const AnalyzerErrorsPopover = ({errors}: IProps) => (
<S.Container>
<Popover
content={<Content errors={errors} />}
placement="right"
title={<S.Title level={3}>Analyzer errors</S.Title>}
>
<S.ErrorIcon />
</Popover>
</S.Container>
);

export default AnalyzerErrorsPopover;
39 changes: 39 additions & 0 deletions web/src/components/AnalyzerErrorsPopover/Content.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {TAnalyzerError} from 'types/TestRun.types';
import * as S from './AnalyzerErrorsPopover.styled';

interface IProps {
errors: TAnalyzerError[];
}

const Content = ({errors}: IProps) => (
<S.ContentContainer>
{errors.map(analyzerError => (
<S.RuleContainer key={analyzerError.ruleName}>
<S.Text>{analyzerError.ruleName}</S.Text>

{analyzerError.errors.length > 1 && (
<>
<div>
<S.Text type="secondary">{analyzerError.ruleErrorDescription}</S.Text>
</div>
<S.List>
{analyzerError.errors.map(error => (
<li key={error.value}>
<S.Text type="secondary">{error.value}</S.Text>
</li>
))}
</S.List>
</>
)}

{analyzerError.errors.length === 1 && (
<div>
<S.Text type="secondary">{analyzerError.errors[0].description}</S.Text>
</div>
)}
</S.RuleContainer>
))}
</S.ContentContainer>
);

export default Content;
2 changes: 2 additions & 0 deletions web/src/components/AnalyzerErrorsPopover/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line no-restricted-exports
export {default} from './AnalyzerErrorsPopover';
5 changes: 4 additions & 1 deletion web/src/components/AttributeList/AttributeList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import {IPropsAttributeRow} from 'components/SpanDetail/SpanDetail';
import {OtelReference} from 'components/TestSpecForm/hooks/useGetOTELSemanticConventionAttributesInfo';
import TestRunOutput from 'models/TestRunOutput.model';
import {TSpanFlatAttribute} from 'types/Span.types';
import {TTestSpecSummary} from 'types/TestRun.types';
import {TAnalyzerError, TTestSpecSummary} from 'types/TestRun.types';
import * as S from './AttributeList.styled';
import EmptyAttributeList from './EmptyAttributeList';

interface IProps {
attributeList: TSpanFlatAttribute[];
searchText?: string;
semanticConventions: OtelReference;
analyzerErrors?: TAnalyzerError[];
testSpecs?: TTestSpecSummary;
testOutputs?: TestRunOutput[];
onCreateTestSpec(attribute: TSpanFlatAttribute): void;
Expand All @@ -21,6 +22,7 @@ const AttributeList = ({
attributeList,
searchText,
semanticConventions,
analyzerErrors,
testSpecs,
testOutputs,
onCreateTestSpec,
Expand All @@ -35,6 +37,7 @@ const AttributeList = ({
attribute={attribute}
searchText={searchText}
semanticConventions={semanticConventions}
analyzerErrors={analyzerErrors}
testSpecs={testSpecs}
testOutputs={testOutputs}
onCreateTestSpec={onCreateTestSpec}
Expand Down
5 changes: 4 additions & 1 deletion web/src/components/SpanDetail/Attributes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import AttributeList from 'components/AttributeList';
import {OtelReference} from 'components/TestSpecForm/hooks/useGetOTELSemanticConventionAttributesInfo';
import TestRunOutput from 'models/TestRunOutput.model';
import {TSpanFlatAttribute} from 'types/Span.types';
import {TTestSpecSummary} from 'types/TestRun.types';
import {TAnalyzerError, TTestSpecSummary} from 'types/TestRun.types';
import {IPropsAttributeRow} from './SpanDetail';
import * as S from './SpanDetail.styled';

interface IProps {
attributeList: TSpanFlatAttribute[];
searchText?: string;
semanticConventions: OtelReference;
analyzerErrors?: TAnalyzerError[];
testSpecs?: TTestSpecSummary;
testOutputs?: TestRunOutput[];
onCreateTestSpec(attribute: TSpanFlatAttribute): void;
Expand All @@ -22,6 +23,7 @@ const Attributes = ({
attributeList,
searchText,
semanticConventions,
analyzerErrors,
testSpecs,
testOutputs,
onCreateTestSpec,
Expand All @@ -41,6 +43,7 @@ const Attributes = ({
attributeList={attributeList}
searchText={searchText}
semanticConventions={semanticConventions}
analyzerErrors={analyzerErrors}
testSpecs={testSpecs}
testOutputs={testOutputs}
onCreateTestSpec={onCreateTestSpec}
Expand Down
2 changes: 2 additions & 0 deletions web/src/components/SpanDetail/SpanDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface IPropsAttributeRow {
attribute: TSpanFlatAttribute;
searchText?: string;
semanticConventions: OtelReference;
analyzerErrors?: TAnalyzerError[];
testSpecs?: TTestSpecSummary;
testOutputs?: TestRunOutput[];
onCreateTestSpec(attribute: TSpanFlatAttribute): void;
Expand Down Expand Up @@ -119,6 +120,7 @@ const SpanDetail = ({onCreateTestSpec = noop, searchText, span, AttributeRowComp
attributeList={filteredAttributes}
searchText={searchText}
semanticConventions={semanticConventions}
analyzerErrors={analyzerErrors}
testSpecs={testSpecs}
testOutputs={testOutputs}
onCreateTestSpec={handleCreateTestSpec}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ export const Container = styled.div`
background-color: ${({theme}) => theme.color.background};
}
`;

export const Footer = styled.div`
align-items: center;
display: flex;
gap: 8px;
`;
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
import {useMemo} from 'react';
import AnalyzerErrorsPopover from 'components/AnalyzerErrorsPopover';
import SpanAttributeService from 'services/SpanAttribute.service';
import * as S from './TraceAttributeRow.styled';
import BaseAttributeRow from '../BaseAttributeRow/BaseAttributeRow';
import {IPropsAttributeRow} from '../SpanDetail';

const AttributeRow = ({
attribute: {key},
attribute,
searchText,
semanticConventions,
analyzerErrors,
onCreateTestSpec,
onCreateOutput,
}: IPropsAttributeRow) => (
<S.Container>
<BaseAttributeRow
attribute={attribute}
searchText={searchText}
semanticConventions={semanticConventions}
onCreateTestSpec={onCreateTestSpec}
onCreateOutput={onCreateOutput}
/>
</S.Container>
);
}: IPropsAttributeRow) => {
const attributeAnalyzerErrors = useMemo(
() => SpanAttributeService.getAttributeAnalyzerErrors(key, analyzerErrors),
[key, analyzerErrors]
);

return (
<S.Container>
<BaseAttributeRow
attribute={attribute}
searchText={searchText}
semanticConventions={semanticConventions}
onCreateTestSpec={onCreateTestSpec}
onCreateOutput={onCreateOutput}
/>

<S.Footer>
{!!attributeAnalyzerErrors.length && <AnalyzerErrorsPopover errors={attributeAnalyzerErrors} />}
</S.Footer>
</S.Container>
);
};

export default AttributeRow;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export const Container = styled.div`
align-items: center;
background-color: ${({theme}) => theme.color.white};
display: flex;
gap: 4px;
padding: 0 12px;
`;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import AnalyzerErrorsPopover from 'components/AnalyzerErrorsPopover';
import {IPropsSubHeader} from '../SpanDetail';
import * as S from './TraceSubHeader.styled';

const TraceSubHeader = ({analyzerErrors}: IPropsSubHeader) => {
return analyzerErrors ? (
<S.Container>
<S.ErrorIcon />
<S.Text type="secondary">Analyzer errors</S.Text>
<AnalyzerErrorsPopover errors={analyzerErrors} />
</S.Container>
) : null;
};
Expand Down
9 changes: 8 additions & 1 deletion web/src/services/SpanAttribute.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {SelectorAttributesBlackList, SelectorAttributesWhiteList} from 'constant
import {Attributes, TraceTestAttributes} from 'constants/SpanAttribute.constants';
import TestRunOutput from 'models/TestRunOutput.model';
import {TSpanFlatAttribute} from 'types/Span.types';
import {TTestSpecSummary} from 'types/TestRun.types';
import {TAnalyzerError, TTestSpecSummary} from 'types/TestRun.types';
import {getObjectIncludesText, isJson} from 'utils/Common';

const flatAttributes = Object.values(Attributes);
Expand Down Expand Up @@ -102,6 +102,13 @@ const SpanAttributeService = () => ({
const lowerCaseAttributeName = attributeName.toLowerCase();
return testOutputs.filter(({name}) => name.toLowerCase().includes(lowerCaseAttributeName));
},

getAttributeAnalyzerErrors(attributeName: String, analyzerErrors: TAnalyzerError[] = []): TAnalyzerError[] {
const lowerCaseAttributeName = attributeName.toLowerCase();
return analyzerErrors.filter(analyzerError =>
analyzerError.errors.some(({value}) => value?.toLowerCase?.()?.includes(lowerCaseAttributeName))
);
},
});

export default SpanAttributeService();

0 comments on commit 6f8135a

Please sign in to comment.