Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new trace details waterfall integration #6708

Draft
wants to merge 33 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
6e1371b
feat: enable waterfall tree construction at query service
vikrantgupta25 Dec 24, 2024
6f33842
feat: frontend base setup and api integration for trace v2
vikrantgupta25 Dec 24, 2024
5da2b39
feat: structure the code in sync with api lifecycle
vikrantgupta25 Dec 26, 2024
ef97148
feat: setup the success state for the spans waterfall model
vikrantgupta25 Dec 26, 2024
8d16ec3
feat: handle the scroll to top and bottom
vikrantgupta25 Dec 26, 2024
d7e6b41
feat: add caching for tree at query service
vikrantgupta25 Dec 26, 2024
e9f5e77
feat: added code comments and TODO
vikrantgupta25 Dec 26, 2024
f9c8850
feat: use range changed to handle loads better
vikrantgupta25 Dec 26, 2024
a451044
feat: temporary changes for inmemory cache
vikrantgupta25 Dec 27, 2024
0087272
feat: base branch for trace details
vikrantgupta25 Dec 27, 2024
44c1f54
Merge branch 'main' into new-trace-detail
vikrantgupta25 Dec 27, 2024
5370b80
Merge branch 'new-trace-detail' into query-service-waterfall
vikrantgupta25 Dec 27, 2024
04a0c75
feat: handle the uncollapsed node and span search better
vikrantgupta25 Dec 28, 2024
efa9b5a
Merge branch 'main' into query-service-waterfall
vikrantgupta25 Jan 4, 2025
a0eefda
feat(trace-details): integrate the new cache for trace details
vikrantgupta25 Jan 4, 2025
cea9010
Merge branch 'main' into query-service-waterfall
vikrantgupta25 Jan 6, 2025
74eb637
feat(waterfall): start building the waterfall UI
vikrantgupta25 Jan 6, 2025
457f959
feat(waterfall): some minor UI enhancements
vikrantgupta25 Jan 6, 2025
25404e8
Merge branch 'main' into query-service-waterfall
vikrantgupta25 Jan 7, 2025
e3ff469
feat(waterfall): timeline UI changes for header and cells
vikrantgupta25 Jan 7, 2025
81a0ef6
feat(waterfall): intersection observer changes
vikrantgupta25 Jan 7, 2025
61b3b45
Merge branch 'main' into query-service-waterfall
vikrantgupta25 Jan 7, 2025
11ea662
Merge branch 'main' into query-service-waterfall
vikrantgupta25 Jan 8, 2025
e1750a1
feat(waterfall): fix build issues
vikrantgupta25 Jan 8, 2025
0fb9f53
feat(waterfall): make the react-table virtualised
vikrantgupta25 Jan 8, 2025
e5ab984
feat(waterfall): virtualise the trace waterfall and add scrollToIndeX…
vikrantgupta25 Jan 8, 2025
af4b8a8
feat(waterfall): handle the interested span and uncollapsed nodes better
vikrantgupta25 Jan 8, 2025
b78dcc2
feat(waterfall): merge branch 'main' into query-service-waterfall
vikrantgupta25 Jan 8, 2025
0cb710e
feat(waterfall): handle infinite scroll
vikrantgupta25 Jan 8, 2025
2025365
feat(waterfall): some more processing to handle waterfall collapse nodes
vikrantgupta25 Jan 8, 2025
212d686
Merge branch 'main' into query-service-waterfall
vikrantgupta25 Jan 8, 2025
180996a
feat(waterfall): some css fixes
vikrantgupta25 Jan 8, 2025
025b02d
feat(waterfall): implement sticky headers and col resize
vikrantgupta25 Jan 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion ee/query-service/app/db/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/jmoiron/sqlx"

cacheV2 "go.signoz.io/signoz/pkg/cache"
basechr "go.signoz.io/signoz/pkg/query-service/app/clickhouseReader"
"go.signoz.io/signoz/pkg/query-service/interfaces"
)
Expand All @@ -17,6 +18,7 @@ type ClickhouseReader struct {
*basechr.ClickHouseReader
}

// dummy
func NewDataConnector(
localDB *sqlx.DB,
promConfigPath string,
Expand All @@ -27,8 +29,9 @@ func NewDataConnector(
cluster string,
useLogsNewSchema bool,
useTraceNewSchema bool,
cacheV2 cacheV2.Cache,
) *ClickhouseReader {
ch := basechr.NewReader(localDB, promConfigPath, lm, maxIdleConns, maxOpenConns, dialTimeout, cluster, useLogsNewSchema, useTraceNewSchema)
ch := basechr.NewReader(localDB, promConfigPath, lm, maxIdleConns, maxOpenConns, dialTimeout, cluster, useLogsNewSchema, useTraceNewSchema, cacheV2)
return &ClickhouseReader{
conn: ch.GetConn(),
appdb: localDB,
Expand Down
18 changes: 10 additions & 8 deletions ee/query-service/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,15 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
return nil, err
}

var c cache.Cache
if serverOptions.CacheConfigPath != "" {
cacheOpts, err := cache.LoadFromYAMLCacheConfigFile(serverOptions.CacheConfigPath)
if err != nil {
return nil, err
}
c = cache.NewCache(cacheOpts)
}

// set license manager as feature flag provider in dao
modelDao.SetFlagProvider(lm)
readerReady := make(chan bool)
Expand All @@ -161,6 +170,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
serverOptions.Cluster,
serverOptions.UseLogsNewSchema,
serverOptions.UseTraceNewSchema,
serverOptions.SigNoz.Cache,
)
go qb.Start(readerReady)
reader = qb
Expand All @@ -175,14 +185,6 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
return nil, err
}
}
var c cache.Cache
if serverOptions.CacheConfigPath != "" {
cacheOpts, err := cache.LoadFromYAMLCacheConfigFile(serverOptions.CacheConfigPath)
if err != nil {
return nil, err
}
c = cache.NewCache(cacheOpts)
}

<-readerReady
rm, err := makeRulesManager(serverOptions.PromConfigPath,
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@sentry/webpack-plugin": "2.22.6",
"@signozhq/design-tokens": "1.1.4",
"@tanstack/react-table": "8.20.6",
"@tanstack/react-virtual": "3.11.2",
"@uiw/react-md-editor": "3.23.5",
"@visx/group": "3.3.0",
"@visx/shape": "3.5.0",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/AppRoutes/pageComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const TraceFilter = Loadable(
);

export const TraceDetail = Loadable(
() => import(/* webpackChunkName: "TraceDetail Page" */ 'pages/TraceDetail'),
() => import(/* webpackChunkName: "TraceDetail Page" */ 'pages/TraceDetailV2'),
);

export const UsageExplorerPage = Loadable(
Expand Down
41 changes: 41 additions & 0 deletions frontend/src/api/trace/getTraceV2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { ApiV2Instance as axios } from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { omit } from 'lodash-es';
import { ErrorResponse, SuccessResponse } from 'types/api';
import {
GetTraceV2PayloadProps,
GetTraceV2SuccessResponse,
} from 'types/api/trace/getTraceV2';

const getTraceV2 = async (
props: GetTraceV2PayloadProps,
): Promise<SuccessResponse<GetTraceV2SuccessResponse> | ErrorResponse> => {
try {
let uncollapsedNodes = [...props.uncollapsedNodes];
if (!props.isInterestedSpanIdUnCollapsed) {
uncollapsedNodes = uncollapsedNodes.filter(
(node) => node !== props.interestedSpanId,
);
}
const postData: GetTraceV2PayloadProps = {
...props,
uncollapsedNodes,
};
const response = await axios.post<GetTraceV2SuccessResponse>(
`/traces/${props.traceId}`,
omit(postData, 'traceId'),
);

return {
statusCode: 200,
error: null,
message: 'Success',
payload: response.data,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};

export default getTraceV2;
101 changes: 74 additions & 27 deletions frontend/src/components/TableV3/TableV3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,47 @@ import {
Table,
useReactTable,
} from '@tanstack/react-table';
import React, { useMemo } from 'react';
import { useVirtualizer, Virtualizer } from '@tanstack/react-virtual';
import cx from 'classnames';
import React, { MutableRefObject, useEffect, useMemo } from 'react';

// here we are manually rendering the table body so that we can memoize the same for performant re-renders
function TableBody<T>({ table }: { table: Table<T> }): JSX.Element {
function TableBody<T>({
table,
virtualizer,
}: {
table: Table<T>;
virtualizer: Virtualizer<HTMLDivElement, Element>;
}): JSX.Element {
const { rows } = table.getRowModel();
return (
<div className="div-tbody">
{table.getRowModel().rows.map((row) => (
<div key={row.id} className="div-tr">
{row.getVisibleCells().map((cell) => (
<div
key={cell.id}
className="div-td"
// we are manually setting the column width here based on the calculated column vars
style={{
width: `calc(var(--col-${cell.column.id}-size) * 1px)`,
}}
>
{cell.renderValue<any>()}
</div>
))}
</div>
))}
{virtualizer.getVirtualItems().map((virtualRow, index) => {
const row = rows[virtualRow.index];
return (
<div
key={virtualRow.index}
className="div-tr"
style={{
height: `${virtualRow.size}px`,
transform: `translateY(${virtualRow.start - index * virtualRow.size}px)`,
}}
>
{row.getVisibleCells().map((cell) => (
<div
key={cell.id}
className="div-td"
// we are manually setting the column width here based on the calculated column vars
style={{
width: `calc(var(--col-${cell.column.id}-size) * 1px)`,
}}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</div>
))}
</div>
);
})}
</div>
);
}
Expand All @@ -40,17 +59,24 @@ const MemoizedTableBody = React.memo(
) as typeof TableBody;

interface ITableConfig {
defaultColumnMinSize: number;
defaultColumnMaxSize: number;
defaultColumnMinSize?: number;
defaultColumnMaxSize?: number;
handleVirtualizerInstanceChanged?: (
instance: Virtualizer<HTMLDivElement, Element>,
) => void;
}
interface ITableV3Props<T> {
columns: ColumnDef<T, any>[];
data: T[];
config: ITableConfig;
customClassName?: string;
virtualiserRef?: MutableRefObject<
Virtualizer<HTMLDivElement, Element> | undefined
>;
}

export function TableV3<T>(props: ITableV3Props<T>): JSX.Element {
const { data, columns, config } = props;
const { data, columns, config, customClassName = '', virtualiserRef } = props;

const table = useReactTable({
data,
Expand All @@ -61,11 +87,26 @@ export function TableV3<T>(props: ITableV3Props<T>): JSX.Element {
},
columnResizeMode: 'onChange',
getCoreRowModel: getCoreRowModel(),
debugTable: true,
debugHeaders: true,
debugColumns: true,
// turn on debug flags to get debug logs from these instances
debugAll: false,
});

const tableRef = React.useRef<HTMLDivElement>(null);
const { rows } = table.getRowModel();
const virtualizer = useVirtualizer({
count: rows.length,
getScrollElement: () => tableRef.current,
estimateSize: () => 54,
overscan: 20,
onChange: config.handleVirtualizerInstanceChanged,
});

useEffect(() => {
if (virtualiserRef) {
virtualiserRef.current = virtualizer;
}
}, [virtualiserRef, virtualizer]);

/**
* Instead of calling `column.getSize()` on every render for every header
* and especially every data cell (very expensive),
Expand All @@ -85,13 +126,14 @@ export function TableV3<T>(props: ITableV3Props<T>): JSX.Element {
}, [table.getState().columnSizingInfo, table.getState().columnSizing]);

return (
<div className="p-2">
<div className={cx('p-2', customClassName)} ref={tableRef}>
{/* Here in the <table> equivalent element (surrounds all table head and data cells), we will define our CSS variables for column sizes */}
<div
className="div-table"
style={{
...columnSizeVars, // Define column sizes on the <table> element
width: table.getTotalSize(),
height: `${virtualizer.getTotalSize()}px`,
}}
>
<div className="div-thead">
Expand Down Expand Up @@ -125,11 +167,16 @@ export function TableV3<T>(props: ITableV3Props<T>): JSX.Element {
</div>
{/* When resizing any column we will render this special memoized version of our table body */}
{table.getState().columnSizingInfo.isResizingColumn ? (
<MemoizedTableBody table={table} />
<MemoizedTableBody table={table} virtualizer={virtualizer} />
) : (
<TableBody table={table} />
<TableBody table={table} virtualizer={virtualizer} />
)}
</div>
</div>
);
}

TableV3.defaultProps = {
customClassName: '',
virtualiserRef: null,
};
1 change: 1 addition & 0 deletions frontend/src/constants/reactQueryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ export const REACT_QUERY_KEY = {
GET_HOST_LIST: 'GET_HOST_LIST',
UPDATE_ALERT_RULE: 'UPDATE_ALERT_RULE',
GET_ACTIVE_LICENSE_V3: 'GET_ACTIVE_LICENSE_V3',
GET_TRACE_V2: 'GET_TRACE_V2',
GET_POD_LIST: 'GET_POD_LIST',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.trace-waterfall {
height: 50vh;
}
Loading
Loading