mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-08 16:49:01 +08:00
Feat: fe: logs pipelines severity parsing processor (#4149)
This commit is contained in:
parent
4644b1c200
commit
112783d618
@ -0,0 +1,25 @@
|
||||
import { Input, InputProps } from 'antd';
|
||||
import { ChangeEventHandler, useState } from 'react';
|
||||
|
||||
function CSVInput({ value, onChange, ...otherProps }: InputProps): JSX.Element {
|
||||
const [inputValue, setInputValue] = useState(
|
||||
((value as string[]) || []).join(', '),
|
||||
);
|
||||
|
||||
const onChangeHandler = (onChange as unknown) as (v: string[]) => void;
|
||||
|
||||
const onInputChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||
const newValue = e.target.value;
|
||||
setInputValue(newValue);
|
||||
|
||||
if (onChangeHandler) {
|
||||
const splitValues = newValue.split(',').map((v) => v.trim());
|
||||
onChangeHandler(splitValues);
|
||||
}
|
||||
};
|
||||
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
return <Input value={inputValue} onChange={onInputChange} {...otherProps} />;
|
||||
}
|
||||
|
||||
export default CSVInput;
|
@ -1,15 +1,13 @@
|
||||
import './styles.scss';
|
||||
|
||||
import { Form, Input, Select } from 'antd';
|
||||
import { ModalFooterTitle } from 'container/PipelinePage/styles';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { formValidationRules } from '../config';
|
||||
import { processorFields, ProcessorFormField } from './config';
|
||||
import {
|
||||
Container,
|
||||
FormWrapper,
|
||||
PipelineIndexIcon,
|
||||
StyledSelect,
|
||||
} from './styles';
|
||||
import CSVInput from './FormFields/CSVInput';
|
||||
import { FormWrapper, PipelineIndexIcon, StyledSelect } from './styles';
|
||||
|
||||
function ProcessorFieldInput({
|
||||
fieldData,
|
||||
@ -25,22 +23,23 @@ function ProcessorFieldInput({
|
||||
return null;
|
||||
}
|
||||
|
||||
// Do not render display elements for hidden inputs.
|
||||
if (fieldData?.hidden) {
|
||||
return (
|
||||
<Container>
|
||||
<PipelineIndexIcon size="small">
|
||||
{Number(fieldData.id) + 1}
|
||||
</PipelineIndexIcon>
|
||||
<FormWrapper>
|
||||
<Form.Item
|
||||
required={false}
|
||||
label={<ModalFooterTitle>{fieldData.fieldName}</ModalFooterTitle>}
|
||||
key={fieldData.id}
|
||||
name={fieldData.name}
|
||||
initialValue={fieldData.initialValue}
|
||||
rules={fieldData.rules ? fieldData.rules : formValidationRules}
|
||||
dependencies={fieldData.dependencies || []}
|
||||
style={{ display: 'none' }}
|
||||
>
|
||||
{fieldData?.options ? (
|
||||
<Input type="hidden" />
|
||||
</Form.Item>
|
||||
);
|
||||
}
|
||||
|
||||
let inputField;
|
||||
if (fieldData?.options) {
|
||||
inputField = (
|
||||
<StyledSelect>
|
||||
{fieldData.options.map(({ value, label }) => (
|
||||
<Select.Option key={value + label} value={value}>
|
||||
@ -48,12 +47,39 @@ function ProcessorFieldInput({
|
||||
</Select.Option>
|
||||
))}
|
||||
</StyledSelect>
|
||||
) : (
|
||||
<Input placeholder={t(fieldData.placeholder)} />
|
||||
);
|
||||
} else if (Array.isArray(fieldData?.initialValue)) {
|
||||
inputField = <CSVInput placeholder={t(fieldData.placeholder)} />;
|
||||
} else {
|
||||
inputField = <Input placeholder={t(fieldData.placeholder)} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
fieldData?.compact
|
||||
? 'compact-processor-field-container'
|
||||
: 'processor-field-container'
|
||||
}
|
||||
>
|
||||
{!fieldData?.compact && (
|
||||
<PipelineIndexIcon size="small">
|
||||
{Number(fieldData.id) + 1}
|
||||
</PipelineIndexIcon>
|
||||
)}
|
||||
<FormWrapper>
|
||||
<Form.Item
|
||||
required={false}
|
||||
label={<ModalFooterTitle>{fieldData.fieldName}</ModalFooterTitle>}
|
||||
name={fieldData.name}
|
||||
initialValue={fieldData.initialValue}
|
||||
rules={fieldData.rules ? fieldData.rules : formValidationRules}
|
||||
dependencies={fieldData.dependencies || []}
|
||||
>
|
||||
{inputField}
|
||||
</Form.Item>
|
||||
</FormWrapper>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -63,9 +89,12 @@ interface ProcessorFieldInputProps {
|
||||
|
||||
function ProcessorForm({ processorType }: ProcessorFormProps): JSX.Element {
|
||||
return (
|
||||
<div>
|
||||
<div className="processor-form-container">
|
||||
{processorFields[processorType]?.map((fieldData: ProcessorFormField) => (
|
||||
<ProcessorFieldInput key={fieldData.id} fieldData={fieldData} />
|
||||
<ProcessorFieldInput
|
||||
key={fieldData.name + String(fieldData.initialValue)}
|
||||
fieldData={fieldData}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
@ -17,6 +17,7 @@ export const processorTypes: Array<ProcessorType> = [
|
||||
{ key: 'json_parser', value: 'json_parser', label: 'Json Parser' },
|
||||
{ key: 'trace_parser', value: 'trace_parser', label: 'Trace Parser' },
|
||||
{ key: 'time_parser', value: 'time_parser', label: 'Timestamp Parser' },
|
||||
{ key: 'severity_parser', value: 'severity_parser', label: 'Severity Parser' },
|
||||
{ key: 'add', value: 'add', label: 'Add' },
|
||||
{ key: 'remove', value: 'remove', label: 'Remove' },
|
||||
// { key: 'retain', value: 'retain', label: 'Retain' }, @Chintan - Commented as per Nitya's suggestion
|
||||
@ -31,13 +32,15 @@ export type ProcessorFieldOption = {
|
||||
value: string;
|
||||
};
|
||||
|
||||
// TODO(Raj): Refactor Processor Form code after putting e2e UI tests in place.
|
||||
export type ProcessorFormField = {
|
||||
id: number;
|
||||
fieldName: string;
|
||||
placeholder: string;
|
||||
name: string | NamePath;
|
||||
rules?: Array<Rule>;
|
||||
initialValue?: string;
|
||||
hidden?: boolean;
|
||||
initialValue?: boolean | string | Array<string>;
|
||||
dependencies?: Array<string | NamePath>;
|
||||
options?: Array<ProcessorFieldOption>;
|
||||
shouldRender?: (form: FormInstance) => boolean;
|
||||
@ -45,6 +48,10 @@ export type ProcessorFormField = {
|
||||
changedValues: ProcessorData,
|
||||
form: FormInstance,
|
||||
) => void;
|
||||
|
||||
// Should this field have its own row or should it
|
||||
// be packed with other compact fields.
|
||||
compact?: boolean;
|
||||
};
|
||||
|
||||
const traceParserFieldValidator: RuleRender = (form) => ({
|
||||
@ -317,6 +324,85 @@ export const processorFields: { [key: string]: Array<ProcessorFormField> } = {
|
||||
initialValue: '%Y-%m-%dT%H:%M:%S.%f%z',
|
||||
},
|
||||
],
|
||||
severity_parser: [
|
||||
{
|
||||
id: 1,
|
||||
fieldName: 'Name of Severity Parsing Processor',
|
||||
placeholder: 'processor_name_placeholder',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
fieldName: 'Parse Severity Value From',
|
||||
placeholder: 'processor_parsefrom_placeholder',
|
||||
name: 'parse_from',
|
||||
initialValue: 'attributes.logLevel',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
fieldName: 'Values for level TRACE',
|
||||
placeholder: 'Specify comma separated values. Eg: trace, 0',
|
||||
name: ['mapping', 'trace'],
|
||||
rules: [],
|
||||
initialValue: ['trace'],
|
||||
compact: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
fieldName: 'Values for level DEBUG',
|
||||
placeholder: 'Specify comma separated values. Eg: debug, 2xx',
|
||||
name: ['mapping', 'debug'],
|
||||
rules: [],
|
||||
initialValue: ['debug'],
|
||||
compact: true,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
fieldName: 'Values for level INFO',
|
||||
placeholder: 'Specify comma separated values. Eg: info, 3xx',
|
||||
name: ['mapping', 'info'],
|
||||
rules: [],
|
||||
initialValue: ['info'],
|
||||
compact: true,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
fieldName: 'Values for level WARN',
|
||||
placeholder: 'Specify comma separated values. Eg: warning, 4xx',
|
||||
name: ['mapping', 'warn'],
|
||||
rules: [],
|
||||
initialValue: ['warn'],
|
||||
compact: true,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
fieldName: 'Values for level ERROR',
|
||||
placeholder: 'Specify comma separated values. Eg: error, 5xx',
|
||||
name: ['mapping', 'error'],
|
||||
rules: [],
|
||||
initialValue: ['error'],
|
||||
compact: true,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
fieldName: 'Values for level FATAL',
|
||||
placeholder: 'Specify comma separated values. Eg: fatal, panic',
|
||||
name: ['mapping', 'fatal'],
|
||||
rules: [],
|
||||
initialValue: ['fatal'],
|
||||
compact: true,
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
fieldName: 'Override Severity Text',
|
||||
placeholder:
|
||||
'Should the parsed severity set both severity and severityText?',
|
||||
name: ['overwrite_text'],
|
||||
rules: [],
|
||||
initialValue: true,
|
||||
hidden: true,
|
||||
},
|
||||
],
|
||||
retain: [
|
||||
{
|
||||
id: 1,
|
||||
|
@ -0,0 +1,27 @@
|
||||
|
||||
.processor-form-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap
|
||||
}
|
||||
|
||||
.processor-field-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
padding: 0rem;
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.compact-processor-field-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
padding: 0rem;
|
||||
min-width: 40%;
|
||||
flex-grow: 1;
|
||||
margin-left: 2.5rem;
|
||||
}
|
@ -5,7 +5,9 @@ import Spinner from 'components/Spinner';
|
||||
import ChangeHistory from 'container/PipelinePage/Layouts/ChangeHistory';
|
||||
import PipelinePage from 'container/PipelinePage/Layouts/Pipeline';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useQuery } from 'react-query';
|
||||
import { SuccessResponse } from 'types/api';
|
||||
@ -77,7 +79,11 @@ function Pipelines(): JSX.Element {
|
||||
return <Spinner height="75vh" tip="Loading Pipelines..." />;
|
||||
}
|
||||
|
||||
return <Tabs defaultActiveKey="pipelines" items={tabItems} />;
|
||||
return (
|
||||
<ErrorBoundary FallbackComponent={ErrorBoundaryFallback}>
|
||||
<Tabs defaultActiveKey="pipelines" items={tabItems} />;
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
export default Pipelines;
|
||||
|
Loading…
x
Reference in New Issue
Block a user