mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-15 22:35:55 +08:00
refactor: add ts support to selectedSpanDetails and TraceGanttChartHelpers, change folder structure
This commit is contained in:
parent
0c12eaf89b
commit
421a102291
@ -1,14 +1,14 @@
|
||||
import React from "react";
|
||||
import { Card, Space, Tabs, Typography } from "antd";
|
||||
import styled from "styled-components";
|
||||
import { pushDStree } from "../../store/actions";
|
||||
import { pushDStree } from "Src/store/actions";
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
interface SelectedSpanDetailsProps {
|
||||
data: pushDStree
|
||||
data: pushDStree;
|
||||
}
|
||||
|
||||
const Title = styled(Text)`
|
||||
@ -17,51 +17,49 @@ const Title = styled(Text)`
|
||||
`;
|
||||
|
||||
const SelectedSpanDetails = (props: SelectedSpanDetailsProps) => {
|
||||
|
||||
let spanTags = props.data.tags;
|
||||
let spanTags = props.data?.tags;
|
||||
let service = props.data?.name?.split(":")[0];
|
||||
let operation = props.data?.name?.split(":")[1];
|
||||
|
||||
return (
|
||||
<Card style={{ border: "none", background: "transparent", padding: 0 }} bodyStyle={{ padding: 0 }}>
|
||||
<Card
|
||||
style={{ border: "none", background: "transparent", padding: 0 }}
|
||||
bodyStyle={{ padding: 0 }}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
|
||||
<strong> Details for selected Span </strong>
|
||||
<Space direction="vertical" size={2}>
|
||||
<Text style={{ marginTop: "18px" }}>
|
||||
Service
|
||||
</Text>
|
||||
<Title style={{ color: "#2D9CDB", fontSize: "12px" }}>
|
||||
{service}
|
||||
</Title>
|
||||
<Text style={{ marginTop: "18px" }}>Service</Text>
|
||||
<Title style={{ color: "#2D9CDB", fontSize: "12px" }}>{service}</Title>
|
||||
</Space>
|
||||
<Space direction="vertical" size={2}>
|
||||
<Text>
|
||||
Operation
|
||||
</Text>
|
||||
<Text style={{ color: "#2D9CDB", fontSize: "12px" }}>
|
||||
{operation}
|
||||
</Text>
|
||||
<Text>Operation</Text>
|
||||
<Text style={{ color: "#2D9CDB", fontSize: "12px" }}>{operation}</Text>
|
||||
</Space>
|
||||
</Space>
|
||||
<Tabs defaultActiveKey="1">
|
||||
<TabPane tab="Tags" key="1">
|
||||
{spanTags && spanTags.map((tags, index) => {
|
||||
{spanTags &&
|
||||
spanTags.map((tags, index) => {
|
||||
return (
|
||||
<>
|
||||
{tags.value && (
|
||||
<>
|
||||
<Text style={{ color: "#BDBDBD", fontSize: "12px", marginBottom: "8px" }}>
|
||||
<Text
|
||||
style={{ color: "#BDBDBD", fontSize: "12px", marginBottom: "8px" }}
|
||||
>
|
||||
{tags.key}
|
||||
</Text>
|
||||
<div style={{
|
||||
<div
|
||||
style={{
|
||||
background: "#4F4F4F",
|
||||
color: "#2D9CDB",
|
||||
fontSize: "12px",
|
||||
padding: "6px 8px",
|
||||
wordBreak: "break-all",
|
||||
marginBottom: "16px",
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{tags.key === "error" ? "true" : tags.value}
|
||||
</div>
|
||||
</>
|
||||
@ -71,21 +69,26 @@ const SelectedSpanDetails = (props: SelectedSpanDetailsProps) => {
|
||||
})}
|
||||
</TabPane>
|
||||
<TabPane tab="Errors" key="2">
|
||||
{spanTags && spanTags
|
||||
{spanTags &&
|
||||
spanTags
|
||||
.filter((tags) => tags.key === "error")
|
||||
.map((error) => (
|
||||
<>
|
||||
<Text style={{ color: "#BDBDBD", fontSize: "12px", marginBottom: "8px" }}>
|
||||
<Text
|
||||
style={{ color: "#BDBDBD", fontSize: "12px", marginBottom: "8px" }}
|
||||
>
|
||||
{error.key}
|
||||
</Text>
|
||||
<div style={{
|
||||
<div
|
||||
style={{
|
||||
background: "#4F4F4F",
|
||||
color: "#2D9CDB",
|
||||
fontSize: "12px",
|
||||
padding: "6px 8px",
|
||||
wordBreak: "break-all",
|
||||
marginBottom: "16px",
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
true
|
||||
</div>
|
||||
</>
|
||||
|
@ -1,41 +0,0 @@
|
||||
// Doing DFS traversal on the tree
|
||||
// resultCount : how many entries you want. where -1 means all possible entries.
|
||||
// func(obj) : takes one element of the data structure and returns true if need to select or not
|
||||
|
||||
// program to implement stack data structure
|
||||
import { isEmpty } from "lodash-es";
|
||||
|
||||
const getTreeData = (tree, callback, resultCount = -1) => {
|
||||
if (resultCount === 0 || isEmpty(tree) || tree.id === "empty") return null;
|
||||
|
||||
let data = tree;
|
||||
let result = [];
|
||||
let stk = [];
|
||||
stk.push(data);
|
||||
|
||||
while (!isEmpty(stk)) {
|
||||
let x = stk[stk.length - 1];
|
||||
|
||||
// marked means seeing the node for the second time.
|
||||
if (x.marked) {
|
||||
delete x.marked;
|
||||
stk.pop();
|
||||
x.map((item) => {
|
||||
if (callback(item) === true) {
|
||||
result.push(item);
|
||||
if (resultCount !== -1 && result.length === resultCount) return result;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
x.marked = true;
|
||||
x.map((item) => {
|
||||
if (item.children.length > 0) {
|
||||
stk.push(item.children);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export default getTreeData;
|
@ -1,13 +0,0 @@
|
||||
.row-styles{
|
||||
cursor: pointer
|
||||
}
|
||||
.hide{
|
||||
display: none;
|
||||
}
|
||||
.ant-tabs-nav-list{
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
.ant-table-body table {
|
||||
margin-bottom: 64px;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
.row-styles {
|
||||
cursor: pointer;
|
||||
}
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
.ant-tabs-nav-list {
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
.ant-table-body table {
|
||||
margin-bottom: 64px;
|
||||
}
|
@ -3,8 +3,8 @@ import { Table, Progress, Tabs, Button, Row, Col } from "antd";
|
||||
import "./TraceGanttChart.css";
|
||||
import { max, isEmpty, has } from "lodash-es";
|
||||
import styled from "styled-components";
|
||||
import getTreeData from "Src/modules/Traces/TraceGantChartHelpers";
|
||||
import { pushDStree } from "../../store/actions";
|
||||
import { pushDStree } from "Src/store/actions";
|
||||
import traverseTreeData from "Src/modules/Traces/TraceGanttChart/TraceGanttChartHelpers";
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
@ -17,11 +17,11 @@ const StyledButton = styled(Button)`
|
||||
`;
|
||||
|
||||
interface TraceGanttChartProps {
|
||||
treeData: pushDStree;
|
||||
treeData: pushDStree[];
|
||||
clickedSpan: pushDStree;
|
||||
selectedSpan: pushDStree;
|
||||
resetZoom: () => {};
|
||||
setSpanTagsInfo: () => {};
|
||||
setSpanTagsInfo: (p: { data: any }) => {};
|
||||
}
|
||||
|
||||
const TraceGanttChart = ({
|
||||
@ -37,12 +37,9 @@ const TraceGanttChart = ({
|
||||
const [defaultExpandedRows, setDefaultExpandedRows] = useState([]);
|
||||
const [sortedTreeData, setSortedTreeData] = useState(treeData);
|
||||
const [isReset, setIsReset] = useState(false);
|
||||
const [rowId, setRowId] = useState(0);
|
||||
const [tabsContainerWidth, setTabsContainerWidth] = useState(0);
|
||||
const tableRef = useRef("");
|
||||
let tabsContainer = document.querySelector(
|
||||
"#collapsable .ant-tabs-nav-list",
|
||||
);
|
||||
let tabsContainer = document.querySelector("#collapsable .ant-tabs-nav-list");
|
||||
|
||||
let tabs = document.querySelectorAll("#collapsable .ant-tabs-tab");
|
||||
|
||||
@ -58,7 +55,7 @@ const TraceGanttChart = ({
|
||||
if (clickedSpan) {
|
||||
setClickedSpanData(clickedSpan);
|
||||
}
|
||||
setTabsContainerWidth(tabsContainer?.offsetWidth)
|
||||
setTabsContainerWidth(tabsContainer?.offsetWidth);
|
||||
}
|
||||
// handleScroll(selectedSpan?.id);
|
||||
}, [sortedTreeData, treeData, clickedSpan]);
|
||||
@ -67,13 +64,11 @@ const TraceGanttChart = ({
|
||||
if (
|
||||
!isEmpty(clickedSpanData) &&
|
||||
clickedSpan &&
|
||||
!selectedRows.includes(clickedSpan.id)
|
||||
&& !isReset
|
||||
!selectedRows.includes(clickedSpan.id) &&
|
||||
!isReset
|
||||
) {
|
||||
setSelectedRows([clickedSpan.id]);
|
||||
getParentKeys(clickedSpan);
|
||||
let keys = [clickedSpan?.id, ...parentKeys];
|
||||
// setDefaultExpandedRows(keys)
|
||||
handleFocusOnSelectedPath("", [clickedSpan.id], clickedSpan);
|
||||
}
|
||||
}, [clickedSpan, selectedRows, isReset, clickedSpanData]);
|
||||
@ -93,11 +88,10 @@ const TraceGanttChart = ({
|
||||
if (!isEmpty(obj.children)) {
|
||||
obj.children.map((item) => {
|
||||
getChildrenKeys(item);
|
||||
})
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEmpty(selectedSpan) && isEmpty(clickedSpan)) {
|
||||
@ -111,7 +105,6 @@ const TraceGanttChart = ({
|
||||
setDefaultExpandedRows([treeData?.[0]?.id]);
|
||||
// /.setSpanTagsInfo({data: treeData?.[0]})
|
||||
}
|
||||
|
||||
}, [selectedSpan, treeData]);
|
||||
|
||||
const getMaxEndTime = (treeData) => {
|
||||
@ -178,14 +171,18 @@ const TraceGanttChart = ({
|
||||
let paddingLeft = 0;
|
||||
let startTime = parseFloat(record.startTime);
|
||||
let duration = parseFloat((record.time / 1000000).toFixed(2));
|
||||
paddingLeft = parseInt(getPaddingLeft(startTime - minGlobal, maxGlobal - minGlobal, tabsContainerWidth));
|
||||
paddingLeft = parseInt(
|
||||
getPaddingLeft(
|
||||
startTime - minGlobal,
|
||||
maxGlobal - minGlobal,
|
||||
tabsContainerWidth,
|
||||
),
|
||||
);
|
||||
let textPadding = paddingLeft;
|
||||
if (paddingLeft === tabsContainerWidth - 20) {
|
||||
textPadding = tabsContainerWidth - 40
|
||||
textPadding = tabsContainerWidth - 40;
|
||||
}
|
||||
length = ((duration / (maxGlobal - startTime)) * 100).toFixed(
|
||||
2,
|
||||
);
|
||||
length = ((duration / (maxGlobal - startTime)) * 100).toFixed(2);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -203,15 +200,22 @@ const TraceGanttChart = ({
|
||||
|
||||
const handleFocusOnSelectedPath = (event, selectedRowsList = selectedRows) => {
|
||||
if (!isEmpty(selectedRowsList)) {
|
||||
let node: pushDStree = getTreeData(
|
||||
treeData,
|
||||
(item: pushDStree) => item.id === selectedRowsList[0],
|
||||
1,
|
||||
);
|
||||
setSpanTagsInfo({ data: node[0] });
|
||||
let node = {};
|
||||
traverseTreeData(treeData, (item: pushDStree) => {
|
||||
if (item.id === selectedRowsList[0]) {
|
||||
node = item;
|
||||
}
|
||||
});
|
||||
|
||||
getParentKeys(node[0]);
|
||||
getChildrenKeys(node[0]);
|
||||
try {
|
||||
setSpanTagsInfo({ data: node });
|
||||
} catch (e) {
|
||||
// TODO: error logging.
|
||||
console.error("Node not found in Tree Data.");
|
||||
}
|
||||
|
||||
getParentKeys(node);
|
||||
getChildrenKeys(node);
|
||||
|
||||
let rows = document.querySelectorAll("#collapsable table tbody tr");
|
||||
Array.from(rows).map((row) => {
|
||||
@ -256,20 +260,25 @@ const TraceGanttChart = ({
|
||||
}
|
||||
},
|
||||
onSelect: (record) => {
|
||||
handleRowOnClick(record)
|
||||
handleRowOnClick(record);
|
||||
},
|
||||
selectedRowKeys: selectedRows,
|
||||
};
|
||||
|
||||
const handleRowOnClick = (record) => {
|
||||
setRowId(record.id);
|
||||
let node = {};
|
||||
traverseTreeData(treeData, (item: pushDStree) => {
|
||||
if (item.id === record.id) {
|
||||
node = item;
|
||||
}
|
||||
});
|
||||
|
||||
let node: pushDStree = getTreeData(
|
||||
treeData,
|
||||
(item: pushDStree) => item.id === record.id,
|
||||
1,
|
||||
);
|
||||
setSpanTagsInfo({ data: node[0] });
|
||||
try {
|
||||
setSpanTagsInfo({ data: node });
|
||||
} catch (e) {
|
||||
// TODO: error logging.
|
||||
console.error("Node not found in TreeData.");
|
||||
}
|
||||
|
||||
const selectedRowKeys = selectedRows;
|
||||
if (selectedRowKeys.indexOf(record.id) >= 0) {
|
||||
@ -310,7 +319,7 @@ const TraceGanttChart = ({
|
||||
refs={tableRef}
|
||||
hideSelectAll={true}
|
||||
columns={columns}
|
||||
rowSelection={{ ...rowSelection, checkStrictly, type:'radio' }}
|
||||
rowSelection={{ ...rowSelection, checkStrictly, type: "radio" }}
|
||||
dataSource={sortedTreeData}
|
||||
rowKey="id"
|
||||
sticky={true}
|
@ -0,0 +1,40 @@
|
||||
import { isEmpty } from "lodash-es";
|
||||
import { pushDStree } from "Src/store/actions";
|
||||
|
||||
interface itemProps {
|
||||
treeData: pushDStree[];
|
||||
marked: boolean;
|
||||
}
|
||||
|
||||
// Doing DFS traversal on the tree.
|
||||
// Callback to be called for each element in the tree once.
|
||||
const traverseTreeData = (
|
||||
tree: pushDStree[],
|
||||
callback: (item: pushDStree) => void,
|
||||
): void => {
|
||||
if (isEmpty(tree) || tree[0].id === "empty") return;
|
||||
let node = { treeData: tree, marked: false };
|
||||
let stk: [itemProps] = [node];
|
||||
|
||||
while (!isEmpty(stk)) {
|
||||
let x = stk[stk.length - 1];
|
||||
|
||||
// marked means seeing the node for the second time.
|
||||
if (x.marked) {
|
||||
x.marked = false;
|
||||
stk.pop();
|
||||
x.treeData.map((item: pushDStree) => {
|
||||
callback(item);
|
||||
});
|
||||
} else {
|
||||
x.marked = true;
|
||||
x.treeData.map((item) => {
|
||||
if (item.children.length > 0) {
|
||||
stk.push({ treeData: item.children, marked: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default traverseTreeData;
|
1
frontend/src/modules/Traces/TraceGanttChart/index.js
Normal file
1
frontend/src/modules/Traces/TraceGanttChart/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from "./TraceGanttChart";
|
@ -6,13 +6,13 @@ import { Card, Row, Col, Space, Affix } from "antd";
|
||||
import * as d3 from "d3";
|
||||
import * as d3Tip from "d3-tip";
|
||||
import "./TraceGraph.css";
|
||||
import { spanToTreeUtil } from "../../utils/spanToTree";
|
||||
import { spanToTreeUtil } from "Src/utils/spanToTree";
|
||||
import {
|
||||
fetchTraceItem,
|
||||
pushDStree,
|
||||
spansWSameTraceIDResponse,
|
||||
} from "../../store/actions";
|
||||
import { StoreState } from "../../store/reducers";
|
||||
import { StoreState } from "Src/store/reducers";
|
||||
import SelectedSpanDetails from "./SelectedSpanDetails";
|
||||
import TraceGanttChart from "./TraceGanttChart";
|
||||
import styled from "styled-components";
|
||||
@ -36,11 +36,11 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
const [selectedSpan, setSelectedSpan] = useState({});
|
||||
const [clickedSpan, setClickedSpan] = useState(null);
|
||||
const [resetZoom, setResetZoom] = useState(false);
|
||||
const [sortedTreeData, setSortedTreeData] = useState<pushDStree>([]);
|
||||
const [sortedTreeData, setSortedTreeData] = useState<pushDStree[]>([]);
|
||||
|
||||
let sortedData = {};
|
||||
|
||||
const getSortedData = (treeData: [pushDStree], parent = {}) => {
|
||||
const getSortedData = (treeData: pushDStree[], parent = {}) => {
|
||||
if (!isEmpty(treeData)) {
|
||||
if (treeData[0].id !== "empty") {
|
||||
return Array.from(treeData).map((item, key) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user