Skip to content

Commit

Permalink
feat: 完善全量日志功能
Browse files Browse the repository at this point in the history
  • Loading branch information
KT-core committed Oct 16, 2024
1 parent 27b8554 commit e1fa828
Show file tree
Hide file tree
Showing 9 changed files with 433 additions and 43 deletions.
20 changes: 19 additions & 1 deletion frontend/src/api/logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const getFullLogChartApi = (params) => {

//查询当前日志规则
export const getLogRuleApi = (params) => {
return post(`/api/log/rule/get`, params)
return get(`/api/log/rule/get`, params)
}
//索引分析(百分比)
export const getLogIndexApi = (params) => {
Expand All @@ -48,3 +48,21 @@ export const updateLogRuleApi = (params) => {
export const deleteLogRuleApi = (params) => {
return post(`/api/log/rule/delete`, params)
}

//——————全量日志->接入外部表
// 获取所有外部表
export const getLogOtherTableListApi = (params) => {
return post(`/api/log/other`, params)
}
//获取外部日志表信息
export const getLogOtherTableInfoApi = (params) => {
return post(`/api/log/other/table`, params)
}
//新增外部日志表信息
export const addLogOtherTableApi = (params) => {
return post(`/api/log/other/add`, params)
}
//新增外部日志表信息
export const deleteLogOtherTableApi = (params) => {
return post(`/api/log/other/delete`, params)
}
3 changes: 3 additions & 0 deletions frontend/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ const AppWrapper = () => {
bodyBg: '#1d222b',
siderBg: '#1d222b',
},
Tree: {
nodeSelectedBg: '#33415580',
},
},
}}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Col, Form, Input, Row, Select } from 'antd'
import React from 'react'
import { AiOutlineInfoCircle } from 'react-icons/ai'
import { IoIosRemoveCircleOutline, IoMdAddCircleOutline } from 'react-icons/io'
const routeKeyList = [
{ label: '_container_id_', value: '_container_id_' },
Expand All @@ -24,6 +25,7 @@ function isValidKey(str) {
return regex.test(str)
}
export default function LogRouteRuleFormList() {
const form = Form.useFormInstance()
return (
<Form.List name={'routeRule'}>
{(fields, { add, remove }, { errors }) => (
Expand All @@ -32,32 +34,57 @@ export default function LogRouteRuleFormList() {
required
label={
<>
路由规则 <IoMdAddCircleOutline onClick={() => add()} size={20} className="mx-2" />
{/* <div className="flex flex-row"> */}
匹配规则{' '}
<IoMdAddCircleOutline
onClick={() => add()}
size={20}
className="mx-2 cursor-pointer"
/>
{/* </div>
<div className="flex flex-row"> */}
<AiOutlineInfoCircle size={16} className="ml-1" />
<span className="text-xs text-gray-400">解析规则只应用于满足匹配规则的日志</span>
{/* </div> */}
</>
}
>
{fields.map((field, index) => (
<div key={field.key} className=" px-3 pt-3 pb-0 rounded relative">
<Row gutter={12}>
<Col span={11} key={index}>
<Form.Item noStyle name={[field.name, 'key']} required>
<Select
options={routeKeyList}
labelInValue
placeholder="选择路由规则Key"
// onChange={(value) => changeGroupLabel('group', value?.key)}
/>
<Form.Item
name={[field.name, 'key']}
required
rules={[
{ required: true, message: '请选择匹配规则Key' },
{
validator: async (_, value) => {
// 获取当前表单中所有的routeRule项
const routeRule = form.getFieldValue('routeRule') || []
// 检查是否有重复的key
const duplicate = routeRule.filter(
(item, i) => item.key.key === value.key && i !== index,
)
if (duplicate.length) {
return Promise.reject('已存在相同的Key')
}
},
},
]}
>
<Select options={routeKeyList} labelInValue placeholder="选择匹配规则Key" />
</Form.Item>
</Col>
<Col span={11} key={index}>
<Form.Item noStyle name={[field.name, 'value']} required>
<Input placeholder="value" />
<Input placeholder="匹配规则value,可输入正则" />
</Form.Item>
</Col>
<Col span={1}>
<IoIosRemoveCircleOutline
size={20}
className="mt-1"
className="mt-1 cursor-pointer"
onClick={() => remove(field.name)}
/>
</Col>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,43 @@
import { Form, Input, Modal } from 'antd'
import React, { useEffect } from 'react'
import { Form, Input, Modal, Select, Tooltip } from 'antd'
import React, { useEffect, useState } from 'react'
import LogRouteRuleFormList from './component/LogRouteRuleFormList'
import { addLogRuleApi, getLogRuleApi, updateLogRuleApi } from 'src/api/logs'
import { showToast } from 'src/utils/toast'
import { useLogsContext } from 'src/contexts/LogsContext'
import { getServiceListApi } from 'src/api/service'
import TextArea from 'antd/es/input/TextArea'
import { AiOutlineInfoCircle } from 'react-icons/ai'

const ConfigLogRuleModal = ({ modalVisible, closeModal, logRuleInfo }) => {
const { getLogTableInfo, updateLoading } = useLogsContext()
const [form] = Form.useForm()
const [serviceList, setServiceList] = useState([])
const getServiceListData = () => {
// 获取7天前的开始时间(当天00:00:00)
const startDate = new Date()
startDate.setDate(new Date().getDate() - 7)
startDate.setHours(0, 0, 0, 0)

// 获取现在
const endDate = new Date()

// 转换为微秒级别的时间戳
const startTime = startDate.getTime() * 1000
const endTime = endDate.getTime() * 1000
getServiceListApi({ startTime, endTime })
.then((res) => {
setServiceList(
(res ?? []).map((service) => ({
label: service,
value: service,
})),
)
})
.catch((error) => {
// console.log(error)
setServiceList([])
})
}
const getLogRule = () => {
getLogRuleApi({
dataBase: logRuleInfo.dataBase,
Expand All @@ -16,7 +46,11 @@ const ConfigLogRuleModal = ({ modalVisible, closeModal, logRuleInfo }) => {
form.setFieldsValue({
parseName: res.parseName,
parseRule: res.parseRule,
// routeRule: res.routeRule,
routeRule: Object.entries(res.routeRule).map(([key, value]) => ({
key: { key: key, value: key },
value: value,
})),
serviceName: res.serviceName,
parseInfo: logRuleInfo.parseInfo,
})
})
Expand All @@ -27,6 +61,7 @@ const ConfigLogRuleModal = ({ modalVisible, closeModal, logRuleInfo }) => {
} else {
form.resetFields()
}
if (modalVisible) getServiceListData()
}, [modalVisible, logRuleInfo])

function addLogRule(logRuleParams) {
Expand Down Expand Up @@ -59,6 +94,7 @@ const ConfigLogRuleModal = ({ modalVisible, closeModal, logRuleInfo }) => {
.validateFields({})
.then(() => {
const formState = form.getFieldsValue(true)
// console.log(formState)
const logRuleParams = {
...formState,
}
Expand All @@ -71,7 +107,7 @@ const ConfigLogRuleModal = ({ modalVisible, closeModal, logRuleInfo }) => {
logRuleParams.routeRule = routeRule
if (Object.keys(routeRule).length === 0) {
showToast({
title: '路由规则不可为空',
title: '匹配规则不可为空',
color: 'danger',
})
return
Expand All @@ -85,7 +121,6 @@ const ConfigLogRuleModal = ({ modalVisible, closeModal, logRuleInfo }) => {
})
.catch((error) => console.log(error))
}

return (
<Modal
title={'日志规则配置'}
Expand All @@ -100,7 +135,12 @@ const ConfigLogRuleModal = ({ modalVisible, closeModal, logRuleInfo }) => {
width={1000}
bodyStyle={{ maxHeight: '80vh', overflowY: 'auto', overflowX: 'hidden' }}
>
<Form layout={'vertical'} form={form} preserve={false}>
<Form
layout={'vertical'}
form={form}
preserve={false}
initialValues={{ routeRule: [{ key: null, value: '' }] }}
>
<Form.Item
label="规则名"
name="parseName"
Expand All @@ -116,7 +156,10 @@ const ConfigLogRuleModal = ({ modalVisible, closeModal, logRuleInfo }) => {
},
]}
>
<Input placeholder="规则名" />
<Input
placeholder="请输入规则名,一经创建暂不支持修改"
disabled={logRuleInfo?.parseName}
/>
</Form.Item>
<Form.Item
label="规则描述"
Expand All @@ -131,10 +174,54 @@ const ConfigLogRuleModal = ({ modalVisible, closeModal, logRuleInfo }) => {
>
<Input placeholder="规则描述" />
</Form.Item>
<Form.Item label="执行应用" name="serviceName">
<Select options={serviceList} placeholder="请选择执行规则的应用"></Select>
</Form.Item>
<LogRouteRuleFormList />

<Form.Item
label="解析规则"
label={
<div className="flex items-center">
解析规则 <AiOutlineInfoCircle size={16} className="ml-1" />
<span className="text-xs text-gray-400">
用于将日志文本解析为独立的字段,加快检索速度。请使用
<a href="https://playground.vrl.dev/" className="underline" target="_blank">
VRL
</a>
语言,查看
<Tooltip
title={`.msg, err = parse_regex(.content, r' \[(?P<level>.*?)\] \[(?P<thread>.*?)\] \[(?P<method>.*?)\(.*?\)\] - (?P<msg>.*)')
if err == null {
.content = encode_json(.msg)
}
del(.msg)`}
>
<span className="px-1 underline cursor-pointer">JAVA</span>
</Tooltip>
<Tooltip
title={`.msg, err = parse_regex(.content, r' \[(?P<level>.*?)\] \[(?P<thread>.*?)\] \[(?P<method>.*?)\(.*?\)\] - (?P<msg>.*)')
if err == null {
.content = encode_json(.msg)
}
del(.msg)`}
>
<span className="px-1 underline cursor-pointer">Go</span>
</Tooltip>
<Tooltip
title={`.msg, err = parse_regex(.content, r' \[(?P<level>.*?)\] \[(?P<thread>.*?)\] \[(?P<method>.*?)\(.*?\)\] - (?P<msg>.*)')
if err == null {
.content = encode_json(.msg)
}
del(.msg)`}
>
<span className="px-1 underline cursor-pointer">Nginx</span>
</Tooltip>
默认规则
</span>
</div>
}
name="parseRule"
rules={[
{
Expand All @@ -143,7 +230,7 @@ const ConfigLogRuleModal = ({ modalVisible, closeModal, logRuleInfo }) => {
},
]}
>
<Input placeholder="解析规则" />
<TextArea placeholder="解析规则" rows={3} />
</Form.Item>
</Form>
</Modal>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Col, Form, Input, Row, Select } from 'antd'
import React from 'react'
import { IoIosRemoveCircleOutline, IoMdAddCircleOutline } from 'react-icons/io'
const routeKeyList = [
{ label: '_container_id_', value: '_container_id_' },
{ label: '_source_', value: '_source_' },
{ label: 'container.image.name', value: 'container.image.name' },
{ label: 'container.ip', value: 'container.ip' },
{ label: 'container.name', value: 'container.name' },
{ label: 'content', value: 'content' },
{ label: 'host.ip', value: 'host.ip' },
{ label: 'host.name', value: 'host.name' },
{ label: 'k8s.namespace.name', value: 'k8s.namespace.name' },
{ label: 'k8s.node.ip', value: 'k8s.node.ip' },
{ label: 'k8s.node.name', value: 'k8s.node.name' },
{ label: 'k8s.pod.name', value: 'k8s.pod.name' },
{ label: 'k8s.pod.uid', value: 'k8s.pod.uid' },
]

function isValidKey(str) {
// 定义正则表达式,确保开头是字母或下划线
const regex = /^[a-zA-Z_].*$/

return regex.test(str)
}
export default function LogRouteRuleFormList() {
return (
<Form.List name={'routeRule'}>
{(fields, { add, remove }, { errors }) => (
<>
<Form.Item
required
label={
<>
匹配日志规则{' '}
<IoMdAddCircleOutline onClick={() => add()} size={20} className="mx-2" />
</>
}
>
{fields.map((field, index) => (
<div key={field.key} className=" px-3 pt-3 pb-0 rounded relative">
<Row gutter={12}>
<Col span={11} key={index}>
<Form.Item noStyle name={[field.name, 'key']} required>
<Select
options={routeKeyList}
labelInValue
placeholder="选择匹配规则Key"
// onChange={(value) => changeGroupLabel('group', value?.key)}
/>
</Form.Item>
</Col>
<Col span={11} key={index}>
<Form.Item noStyle name={[field.name, 'value']} required>
<Input placeholder="value" />
</Form.Item>
</Col>
<Col span={1}>
<IoIosRemoveCircleOutline
size={20}
className="mt-1"
onClick={() => remove(field.name)}
/>
</Col>
</Row>
</div>
))}
</Form.Item>
</>
)}
</Form.List>
)
}
Loading

0 comments on commit e1fa828

Please sign in to comment.