mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
fix: Allow to share open log in search dashboard tile (#412)
This commit is contained in:
parent
d42492069b
commit
3260f08650
7 changed files with 54 additions and 11 deletions
5
.changeset/rare-seals-fly.md
Normal file
5
.changeset/rare-seals-fly.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@hyperdx/app': patch
|
||||
---
|
||||
|
||||
Allow to share open log in search dashboard tile
|
||||
|
|
@ -1982,11 +1982,13 @@ function useTraceProperties({
|
|||
|
||||
function SidePanelHeader({
|
||||
logData,
|
||||
shareUrl,
|
||||
onPropertyAddClick,
|
||||
generateSearchUrl,
|
||||
onClose,
|
||||
}: {
|
||||
logData: any;
|
||||
shareUrl: string;
|
||||
onClose: VoidFunction;
|
||||
onPropertyAddClick?: (name: string, value: string) => void;
|
||||
generateSearchUrl: (
|
||||
|
|
@ -1997,7 +1999,7 @@ function SidePanelHeader({
|
|||
}) {
|
||||
const parsedProperties = useParsedLogProperties(logData);
|
||||
|
||||
const date = new Date(logData.timestamp);
|
||||
const date = useMemo(() => new Date(logData.timestamp), [logData.timestamp]);
|
||||
const start = add(date, { minutes: -240 });
|
||||
const end = add(date, { minutes: 240 });
|
||||
|
||||
|
|
@ -2093,7 +2095,7 @@ function SidePanelHeader({
|
|||
</div>
|
||||
)}
|
||||
<CopyToClipboard
|
||||
text={window.location.href}
|
||||
text={shareUrl}
|
||||
onCopy={() => {
|
||||
notifications.show({
|
||||
color: 'green',
|
||||
|
|
@ -2564,6 +2566,7 @@ const checkKeyExistsInLogData = (key: string, logData: any) => {
|
|||
|
||||
export default function LogSidePanel({
|
||||
logId,
|
||||
q,
|
||||
onClose,
|
||||
onPropertyAddClick,
|
||||
generateSearchUrl,
|
||||
|
|
@ -2572,7 +2575,9 @@ export default function LogSidePanel({
|
|||
isNestedPanel = false,
|
||||
displayedColumns,
|
||||
toggleColumn,
|
||||
shareUrl: shareUrlProp,
|
||||
}: {
|
||||
q?: string;
|
||||
logId: string | undefined;
|
||||
onClose: () => void;
|
||||
onPropertyAddClick?: (name: string, value: string) => void;
|
||||
|
|
@ -2590,6 +2595,7 @@ export default function LogSidePanel({
|
|||
isNestedPanel?: boolean;
|
||||
displayedColumns?: string[];
|
||||
toggleColumn?: (column: string) => void;
|
||||
shareUrl?: string;
|
||||
}) {
|
||||
const contextZIndex = useZIndex();
|
||||
|
||||
|
|
@ -2692,6 +2698,23 @@ export default function LogSidePanel({
|
|||
}
|
||||
}, ['mouseup', 'touchend']);
|
||||
|
||||
const shareUrl = useMemo(() => {
|
||||
if (shareUrlProp) {
|
||||
return shareUrlProp;
|
||||
}
|
||||
if (logData == null) {
|
||||
return window.location.href;
|
||||
}
|
||||
return `${window.location.origin}/search?${new URLSearchParams({
|
||||
lid: logData.id,
|
||||
sk: logData.sort_key,
|
||||
from: start.getTime().toString(),
|
||||
to: end.getTime().toString(),
|
||||
ts: date.getTime().toString(),
|
||||
q: q ?? '',
|
||||
}).toString()}`;
|
||||
}, [shareUrlProp, logData, start, end, date, q]);
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
customIdSuffix={`log-side-panel-${logId}`}
|
||||
|
|
@ -2714,6 +2737,7 @@ export default function LogSidePanel({
|
|||
<>
|
||||
<SidePanelHeader
|
||||
logData={logData}
|
||||
shareUrl={shareUrl}
|
||||
onPropertyAddClick={onPropertyAddClick}
|
||||
generateSearchUrl={generateSearchUrl}
|
||||
onClose={_onClose}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import { useLocalStorage, usePrevious, useWindowSize } from './utils';
|
|||
import { TIME_TOKENS } from './utils';
|
||||
|
||||
import styles from '../styles/LogTable.module.scss';
|
||||
|
||||
type Row = Record<string, any> & { duration: number };
|
||||
type AccessorFn = (row: Row, column: string) => any;
|
||||
|
||||
|
|
@ -46,6 +45,8 @@ const ACCESSOR_MAP: Record<string, AccessorFn> = {
|
|||
default: (row, column) => row[column],
|
||||
};
|
||||
|
||||
const MAX_SCROLL_FETCH_NEW_PAGE_ATTEMPTS = 20;
|
||||
|
||||
function retrieveColumnValue(column: string, row: Row): any {
|
||||
const accessor = ACCESSOR_MAP[column] ?? ACCESSOR_MAP.default;
|
||||
return accessor(row, column);
|
||||
|
|
@ -243,7 +244,7 @@ export const RawLogTable = memo(
|
|||
timestamp: string;
|
||||
}[];
|
||||
isLoading: boolean;
|
||||
fetchNextPage: () => any;
|
||||
fetchNextPage: (arg0?: { cb?: VoidFunction }) => any;
|
||||
onRowExpandClick: (id: string, sortKey: string) => void;
|
||||
// onPropertySearchClick: (
|
||||
// name: string,
|
||||
|
|
@ -522,6 +523,8 @@ export const RawLogTable = memo(
|
|||
// Scroll to log id if it's not in window yet
|
||||
const [scrolledToHighlightedLine, setScrolledToHighlightedLine] =
|
||||
useState(false);
|
||||
const [scrolledToHighlightedLineCount, setScrolledToHighlightedLineCount] =
|
||||
useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
|
|
@ -534,7 +537,15 @@ export const RawLogTable = memo(
|
|||
|
||||
const rowIdx = dedupLogs.findIndex(l => l.id === highlightedLineId);
|
||||
if (rowIdx == -1) {
|
||||
fetchNextPage();
|
||||
if (
|
||||
scrolledToHighlightedLineCount < MAX_SCROLL_FETCH_NEW_PAGE_ATTEMPTS
|
||||
) {
|
||||
fetchNextPage({
|
||||
cb: () => {
|
||||
setScrolledToHighlightedLineCount(prev => prev + 1);
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setScrolledToHighlightedLine(true);
|
||||
if (
|
||||
|
|
@ -551,9 +562,8 @@ export const RawLogTable = memo(
|
|||
fetchNextPage,
|
||||
rowVirtualizer,
|
||||
scrolledToHighlightedLine,
|
||||
// Needed to make sure we call this again when the log search loading
|
||||
// state is done to fetch next page
|
||||
isLoading,
|
||||
scrolledToHighlightedLineCount,
|
||||
]);
|
||||
|
||||
const shiftHighlightedLineId = useCallback(
|
||||
|
|
@ -926,7 +936,7 @@ export default function LogTable({
|
|||
logs={searchResults ?? []}
|
||||
isLoading={isLoading}
|
||||
fetchNextPage={useCallback(
|
||||
() => fetchNextPage({ limit: 200 }),
|
||||
(args: any) => fetchNextPage({ limit: 200, ...args }),
|
||||
[fetchNextPage],
|
||||
)}
|
||||
// onPropertySearchClick={onPropertySearchClick}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ export function LogTableWithSidePanel({
|
|||
generateChartUrl={generateChartUrl}
|
||||
displayedColumns={displayedColumns}
|
||||
toggleColumn={toggleColumn}
|
||||
q={searchedQuery}
|
||||
/>
|
||||
</Portal>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ export function VercelIcon({ style, width }: IconProps) {
|
|||
viewBox="0 0 512 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path fill-rule="evenodd" d="M256,48,496,464H16Z" />
|
||||
<path fillRule="evenodd" d="M256,48,496,464H16Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
|
@ -294,7 +294,7 @@ export function TerraformFlatIcon({ width }: IconProps) {
|
|||
viewBox="0 0 44 44"
|
||||
width={width}
|
||||
>
|
||||
<g clip-rule="evenodd" fill-rule="evenodd">
|
||||
<g clipRule="evenodd" fillRule="evenodd">
|
||||
<path
|
||||
d="m16.664 7.384 10.468 6.042v12.085l-10.468-6.041z"
|
||||
fill="currentColor"
|
||||
|
|
|
|||
|
|
@ -356,6 +356,7 @@ const LogViewerContainer = memo(function LogViewerContainer({
|
|||
generateChartUrl={generateChartUrl}
|
||||
displayedColumns={displayedColumns}
|
||||
toggleColumn={toggleColumn}
|
||||
shareUrl={window.location.href}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
<LogTable
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ function useSearchEventStream(
|
|||
]);
|
||||
|
||||
const fetchNextPage = useCallback(
|
||||
(params?: { limit?: number }) => {
|
||||
(params?: { limit?: number; cb?: VoidFunction }) => {
|
||||
// Make sure we don't try to fetch again when we're already fetching
|
||||
// Make sure lastFetchStatusRef is not null, as that means we haven't done an initial fetch yet
|
||||
if (
|
||||
|
|
@ -286,6 +286,8 @@ function useSearchEventStream(
|
|||
fetchResults({
|
||||
pageParam: results.data.length,
|
||||
limit: params?.limit,
|
||||
}).then(() => {
|
||||
params?.cb?.();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue