@parca/profile 0.16.359 → 0.16.360
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/Callgraph/utils.d.ts +6 -6
- package/dist/GraphTooltip/index.d.ts +5 -5
- package/dist/MetricsGraph/MetricsTooltip/index.js +4 -4
- package/dist/MetricsGraph/index.js +3 -2
- package/dist/ProfileIcicleGraph/ActionButtons/GroupByDropdown.d.ts +0 -1
- package/dist/ProfileIcicleGraph/ActionButtons/RuntimeFilterDropdown.d.ts +0 -1
- package/dist/ProfileIcicleGraph/ActionButtons/SortBySelect.d.ts +0 -1
- package/dist/ProfileSource.d.ts +2 -5
- package/dist/ProfileSource.js +9 -7
- package/dist/ProfileView/ProfileViewContext.d.ts +1 -1
- package/dist/ProfileView/index.js +2 -1
- package/dist/Table/ColumnsVisibility.d.ts +0 -1
- package/package.json +6 -6
- package/src/MetricsGraph/MetricsTooltip/index.tsx +11 -4
- package/src/MetricsGraph/index.tsx +3 -2
- package/src/ProfileSource.tsx +11 -15
- package/src/ProfileView/index.tsx +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 0.16.360 (2024-04-25)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
6
10
|
## 0.16.359 (2024-04-15)
|
|
7
11
|
|
|
8
12
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -2,12 +2,12 @@ import { CallgraphEdge, CallgraphNode } from '@parca/client';
|
|
|
2
2
|
export declare const pixelsToInches: (pixels: number) => number;
|
|
3
3
|
export declare const getCurvePoints: ({ pos, xScale, yScale, source, target, offset, isSelfLoop, }: {
|
|
4
4
|
pos: string;
|
|
5
|
-
xScale?: (
|
|
6
|
-
yScale?: (
|
|
7
|
-
source?: number[]
|
|
8
|
-
target?: number[]
|
|
9
|
-
isSelfLoop?: boolean
|
|
10
|
-
offset?: number
|
|
5
|
+
xScale?: (pos: number) => number;
|
|
6
|
+
yScale?: (pos: number) => number;
|
|
7
|
+
source?: number[];
|
|
8
|
+
target?: number[];
|
|
9
|
+
isSelfLoop?: boolean;
|
|
10
|
+
offset?: number;
|
|
11
11
|
}) => number[];
|
|
12
12
|
export declare const jsonToDot: ({ graph, colorRange, }: {
|
|
13
13
|
graph: {
|
|
@@ -31,11 +31,11 @@ export declare const GraphTooltipContent: ({ hoveringNode, unit, total, totalUnf
|
|
|
31
31
|
total: bigint;
|
|
32
32
|
totalUnfiltered: bigint;
|
|
33
33
|
isFixed: boolean;
|
|
34
|
-
strings?: string[]
|
|
35
|
-
mappings?: Mapping[]
|
|
36
|
-
locations?: Location[]
|
|
37
|
-
functions?: ParcaFunction[]
|
|
38
|
-
type?: string
|
|
34
|
+
strings?: string[];
|
|
35
|
+
mappings?: Mapping[];
|
|
36
|
+
locations?: Location[];
|
|
37
|
+
functions?: ParcaFunction[];
|
|
38
|
+
type?: string;
|
|
39
39
|
}) => JSX.Element;
|
|
40
40
|
declare const GraphTooltip: ({ x, y, unit, total, totalUnfiltered, hoveringNode: hoveringNodeProp, contextElement, isFixed, virtualContextElement, strings, mappings, locations, functions, type, }: GraphTooltipProps) => JSX.Element;
|
|
41
41
|
export default GraphTooltip;
|
|
@@ -14,9 +14,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
14
14
|
import { useEffect, useState } from 'react';
|
|
15
15
|
import { Icon } from '@iconify/react';
|
|
16
16
|
import { usePopper } from 'react-popper';
|
|
17
|
-
import { TextWithTooltip } from '@parca/components';
|
|
18
|
-
import { formatDate, valueFormatter } from '@parca/utilities';
|
|
19
|
-
import { timeFormat } from '../../';
|
|
17
|
+
import { TextWithTooltip, useParcaContext } from '@parca/components';
|
|
18
|
+
import { formatDate, timePattern, valueFormatter } from '@parca/utilities';
|
|
20
19
|
const virtualElement = {
|
|
21
20
|
getBoundingClientRect: () => {
|
|
22
21
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
@@ -44,6 +43,7 @@ function generateGetBoundingClientRect(contextElement, x = 0, y = 0) {
|
|
|
44
43
|
});
|
|
45
44
|
}
|
|
46
45
|
const MetricsTooltip = ({ x, y, highlighted, contextElement, sampleUnit, delta, }) => {
|
|
46
|
+
const { timezone } = useParcaContext();
|
|
47
47
|
const [popperElement, setPopperElement] = useState(null);
|
|
48
48
|
const { styles, attributes, ...popperProps } = usePopper(virtualElement, popperElement, {
|
|
49
49
|
placement: 'auto-start',
|
|
@@ -73,7 +73,7 @@ const MetricsTooltip = ({ x, y, highlighted, contextElement, sampleUnit, delta,
|
|
|
73
73
|
}, [x, y, contextElement, update]);
|
|
74
74
|
const nameLabel = highlighted?.labels.find(e => e.name === '__name__');
|
|
75
75
|
const highlightedNameLabel = nameLabel !== undefined ? nameLabel : { name: '', value: '' };
|
|
76
|
-
return (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, className: "z-10", children: _jsx("div", { className: "flex max-w-md", children: _jsx("div", { className: "m-auto", children: _jsx("div", { className: "rounded-lg border-gray-300 bg-gray-50 p-3 opacity-90 shadow-lg dark:border-gray-500 dark:bg-gray-900", style: { borderWidth: 1 }, children: _jsx("div", { className: "flex flex-row", children: _jsxs("div", { className: "ml-2 mr-6", children: [_jsx("span", { className: "font-semibold", children: highlightedNameLabel.value }), _jsx("span", { className: "my-2 block text-gray-700 dark:text-gray-300", children: _jsx("table", { className: "table-auto", children: _jsxs("tbody", { children: [delta ? (_jsxs(_Fragment, { children: [_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Per Second" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.valuePerSecond, sampleUnit === 'nanoseconds' ? 'CPU Cores' : sampleUnit, 5) })] }), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Total" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.value, sampleUnit, 2) })] })] })) : (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Value" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.valuePerSecond, sampleUnit, 5) })] })), highlighted.duration > 0 && (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Duration" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.duration, 'nanoseconds', 2) })] })), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "At" }), _jsx("td", { className: "w-3/4", children: formatDate(highlighted.timestamp,
|
|
76
|
+
return (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, className: "z-10", children: _jsx("div", { className: "flex max-w-md", children: _jsx("div", { className: "m-auto", children: _jsx("div", { className: "rounded-lg border-gray-300 bg-gray-50 p-3 opacity-90 shadow-lg dark:border-gray-500 dark:bg-gray-900", style: { borderWidth: 1 }, children: _jsx("div", { className: "flex flex-row", children: _jsxs("div", { className: "ml-2 mr-6", children: [_jsx("span", { className: "font-semibold", children: highlightedNameLabel.value }), _jsx("span", { className: "my-2 block text-gray-700 dark:text-gray-300", children: _jsx("table", { className: "table-auto", children: _jsxs("tbody", { children: [delta ? (_jsxs(_Fragment, { children: [_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Per Second" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.valuePerSecond, sampleUnit === 'nanoseconds' ? 'CPU Cores' : sampleUnit, 5) })] }), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Total" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.value, sampleUnit, 2) })] })] })) : (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Value" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.valuePerSecond, sampleUnit, 5) })] })), highlighted.duration > 0 && (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Duration" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.duration, 'nanoseconds', 2) })] })), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "At" }), _jsx("td", { className: "w-3/4", children: formatDate(highlighted.timestamp, timePattern(timezone), timezone) })] })] }) }) }), _jsx("span", { className: "my-2 block text-gray-500", children: highlighted.labels
|
|
77
77
|
.filter((label) => label.name !== '__name__')
|
|
78
78
|
.map((label) => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", children: _jsx(TextWithTooltip, { text: `${label.name}="${label.value}"`, maxTextLength: 37, id: `tooltip-${label.name}-${label.value}` }) }, label.name))) }), _jsxs("div", { className: "flex w-full items-center gap-1 text-xs text-gray-500", children: [_jsx(Icon, { icon: "iconoir:mouse-button-right" }), _jsx("div", { children: "Right click to add labels to query." })] })] }) }) }) }) }) }));
|
|
79
79
|
};
|
|
@@ -16,7 +16,7 @@ import * as d3 from 'd3';
|
|
|
16
16
|
import { pointer } from 'd3-selection';
|
|
17
17
|
import throttle from 'lodash.throttle';
|
|
18
18
|
import { useContextMenu } from 'react-contexify';
|
|
19
|
-
import { DateTimeRange } from '@parca/components';
|
|
19
|
+
import { DateTimeRange, useParcaContext } from '@parca/components';
|
|
20
20
|
import { formatDate, formatForTimespan, getPrecision, sanitizeHighlightedValues, valueFormatter, } from '@parca/utilities';
|
|
21
21
|
import MetricsCircle from '../MetricsCircle';
|
|
22
22
|
import MetricsSeries from '../MetricsSeries';
|
|
@@ -37,6 +37,7 @@ export const parseValue = (value) => {
|
|
|
37
37
|
const lineStroke = '1px';
|
|
38
38
|
const lineStrokeHover = '2px';
|
|
39
39
|
export const RawMetricsGraph = ({ data, from, to, profile, onSampleClick, addLabelMatcher, setTimeRange, width, height = 50, margin = 0, sampleUnit, }) => {
|
|
40
|
+
const { timezone } = useParcaContext();
|
|
40
41
|
const graph = useRef(null);
|
|
41
42
|
const [dragging, setDragging] = useState(false);
|
|
42
43
|
const [hovering, setHovering] = useState(false);
|
|
@@ -265,7 +266,7 @@ export const RawMetricsGraph = ({ data, from, to, profile, onSampleClick, addLab
|
|
|
265
266
|
transform: `translate(0, ${yScale(d)})`, children: [_jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x2: -6 }), _jsx("text", { fill: "currentColor", x: -9, dy: '0.32em', children: valueFormatter(d, yAxisUnit, decimals) })] }, `tick-${i}`), _jsx("g", { children: _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(from), x2: xScale(to), y1: yScale(d), y2: yScale(d) }) }, `grid-${i}`)] }, `${i.toString()}-${d.toString()}`));
|
|
266
267
|
}), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: 0, x2: 0, y1: 0, y2: height - margin }), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(to), x2: xScale(to), y1: 0, y2: height - margin }), _jsx("g", { transform: `translate(${-margin}, ${(height - margin) / 2}) rotate(270)`, children: _jsx("text", { fill: "currentColor", dy: "-0.7em", className: "text-sm capitalize", textAnchor: "middle", children: yAxisLabel }) })] }), _jsxs("g", { className: "x axis", fill: "none", fontSize: "10", textAnchor: "middle", transform: `translate(0,${height - margin})`, children: [xScale.ticks(5).map((d, i) => (_jsxs(Fragment, { children: [_jsxs("g", { className: "tick",
|
|
267
268
|
/* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
|
|
268
|
-
transform: `translate(${xScale(d)}, 0)`, children: [_jsx("line", { y2: 6, className: "stroke-gray-300 dark:stroke-gray-500" }), _jsx("text", { fill: "currentColor", dy: ".71em", y: 9, children: formatDate(d, formatForTimespan(from, to)) })] }, `tick-${i}`), _jsx("g", { children: _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(d), x2: xScale(d), y1: 0, y2: -height + margin }) }, `grid-${i}`)] }, `${i.toString()}-${d.toString()}`))), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(from), x2: xScale(to), y1: 0, y2: 0 }), _jsx("g", { transform: `translate(${(width - 2.5 * margin) / 2}, ${margin / 2})`, children: _jsx("text", { fill: "currentColor", dy: ".71em", y: 5, className: "text-sm", children: "Time" }) })] }), _jsx("g", { className: "lines fill-transparent", children: series.map((s, i) => (_jsx("g", { className: "line", children: _jsx(MetricsSeries, { data: s, line: l, color: color(i.toString()), strokeWidth: hovering && highlighted != null && i === highlighted.seriesIndex
|
|
269
|
+
transform: `translate(${xScale(d)}, 0)`, children: [_jsx("line", { y2: 6, className: "stroke-gray-300 dark:stroke-gray-500" }), _jsx("text", { fill: "currentColor", dy: ".71em", y: 9, children: formatDate(d, formatForTimespan(from, to), timezone) })] }, `tick-${i}`), _jsx("g", { children: _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(d), x2: xScale(d), y1: 0, y2: -height + margin }) }, `grid-${i}`)] }, `${i.toString()}-${d.toString()}`))), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(from), x2: xScale(to), y1: 0, y2: 0 }), _jsx("g", { transform: `translate(${(width - 2.5 * margin) / 2}, ${margin / 2})`, children: _jsx("text", { fill: "currentColor", dy: ".71em", y: 5, className: "text-sm", children: "Time" }) })] }), _jsx("g", { className: "lines fill-transparent", children: series.map((s, i) => (_jsx("g", { className: "line", children: _jsx(MetricsSeries, { data: s, line: l, color: color(i.toString()), strokeWidth: hovering && highlighted != null && i === highlighted.seriesIndex
|
|
269
270
|
? lineStrokeHover
|
|
270
271
|
: lineStroke, xScale: xScale, yScale: yScale }) }, i))) }), hovering && highlighted != null && (_jsx("g", { className: "circle-group", ref: metricPointRef, style: { fill: color(highlighted.seriesIndex.toString()) }, children: _jsx(MetricsCircle, { cx: highlighted.x, cy: highlighted.y }) })), selected != null && (_jsx("g", { className: "circle-group", style: selected?.seriesIndex != null
|
|
271
272
|
? { fill: color(selected.seriesIndex.toString()) }
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
1
|
declare const RuntimeFilterDropdown: ({ showRuntimeRuby, toggleShowRuntimeRuby, showRuntimePython, toggleShowRuntimePython, showInterpretedOnly, toggleShowInterpretedOnly, }: {
|
|
3
2
|
showRuntimeRuby: boolean;
|
|
4
3
|
toggleShowRuntimeRuby: () => void;
|
package/dist/ProfileSource.d.ts
CHANGED
|
@@ -5,8 +5,7 @@ export interface ProfileSource {
|
|
|
5
5
|
QueryRequest: () => QueryRequest;
|
|
6
6
|
ProfileType: () => ProfileType;
|
|
7
7
|
DiffSelection: () => ProfileDiffSelection;
|
|
8
|
-
|
|
9
|
-
toString: () => string;
|
|
8
|
+
toString: (timezone?: string) => string;
|
|
10
9
|
}
|
|
11
10
|
export interface ProfileSelection {
|
|
12
11
|
ProfileName: () => string;
|
|
@@ -16,7 +15,6 @@ export interface ProfileSelection {
|
|
|
16
15
|
ProfileSource: () => ProfileSource;
|
|
17
16
|
Type: () => string;
|
|
18
17
|
}
|
|
19
|
-
export declare const timeFormat = "yyyy-MM-dd HH:mm:ss '(UTC)'";
|
|
20
18
|
export declare function ParamsString(params: {
|
|
21
19
|
[key: string]: string;
|
|
22
20
|
}): string;
|
|
@@ -60,7 +58,6 @@ export declare class MergedProfileSource implements ProfileSource {
|
|
|
60
58
|
DiffSelection(): ProfileDiffSelection;
|
|
61
59
|
QueryRequest(): QueryRequest;
|
|
62
60
|
ProfileType(): ProfileType;
|
|
63
|
-
Describe(): JSX.Element;
|
|
64
61
|
stringMatchers(): string[];
|
|
65
|
-
toString(): string;
|
|
62
|
+
toString(timezone?: string): string;
|
|
66
63
|
}
|
package/dist/ProfileSource.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
// Copyright 2022 The Parca Authors
|
|
3
3
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
// you may not use this file except in compliance with the License.
|
|
@@ -14,7 +14,12 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
14
14
|
import { ProfileDiffSelection_Mode, QueryRequest_Mode, QueryRequest_ReportType, Timestamp, } from '@parca/client';
|
|
15
15
|
import { ProfileType, Query } from '@parca/parser';
|
|
16
16
|
import { formatDate } from '@parca/utilities';
|
|
17
|
-
|
|
17
|
+
const timeFormat = (timezone) => {
|
|
18
|
+
if (timezone !== undefined) {
|
|
19
|
+
return 'yyyy-MM-dd HH:mm:ss';
|
|
20
|
+
}
|
|
21
|
+
return "yyyy-MM-dd HH:mm:ss '(UTC)'";
|
|
22
|
+
};
|
|
18
23
|
export function ParamsString(params) {
|
|
19
24
|
return Object.keys(params)
|
|
20
25
|
.map(function (key) {
|
|
@@ -153,15 +158,12 @@ export class MergedProfileSource {
|
|
|
153
158
|
ProfileType() {
|
|
154
159
|
return ProfileType.fromString(Query.parse(this.query.toString()).profileName());
|
|
155
160
|
}
|
|
156
|
-
Describe() {
|
|
157
|
-
return (_jsxs("a", { children: ["Merge of \"", this.query.toString(), "\" from ", formatDate(this.mergeFrom, timeFormat), ' ', "to ", formatDate(this.mergeTo, timeFormat)] }));
|
|
158
|
-
}
|
|
159
161
|
stringMatchers() {
|
|
160
162
|
return this.query.matchers
|
|
161
163
|
.filter((m) => m.key !== '__name__')
|
|
162
164
|
.map((m) => `${m.key}=${m.value}`);
|
|
163
165
|
}
|
|
164
|
-
toString() {
|
|
165
|
-
return `merged profiles of query "${this.query.toString()}" from ${formatDate(this.mergeFrom, timeFormat)} to ${formatDate(this.mergeTo, timeFormat)}`;
|
|
166
|
+
toString(timezone) {
|
|
167
|
+
return `merged profiles of query "${this.query.toString()}" from ${formatDate(this.mergeFrom, timeFormat(timezone), timezone)} to ${formatDate(this.mergeTo, timeFormat(timezone), timezone)}`;
|
|
166
168
|
}
|
|
167
169
|
}
|
|
@@ -9,7 +9,7 @@ export declare const defaultValue: Props;
|
|
|
9
9
|
declare const ProfileViewContext: import("react").Context<Props>;
|
|
10
10
|
export declare const ProfileViewContextProvider: ({ children, value, }: {
|
|
11
11
|
children: ReactNode;
|
|
12
|
-
value?: Props
|
|
12
|
+
value?: Props;
|
|
13
13
|
}) => JSX.Element;
|
|
14
14
|
export declare const useProfileViewContext: () => Props;
|
|
15
15
|
export default ProfileViewContext;
|
|
@@ -39,6 +39,7 @@ function arrayEquals(a, b) {
|
|
|
39
39
|
a.every((val, index) => val === b[index]));
|
|
40
40
|
}
|
|
41
41
|
export const ProfileView = ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, sampleUnit, profileSource, queryClient, navigateTo, onDownloadPProf, pprofDownloading, compare, }) => {
|
|
42
|
+
const { timezone } = useParcaContext();
|
|
42
43
|
const { ref, dimensions } = useContainerDimensions();
|
|
43
44
|
const [curPath, setCurPath] = useState([]);
|
|
44
45
|
const [rawDashboardItems = ['icicle'], setDashboardItems] = useURLState({
|
|
@@ -144,7 +145,7 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
|
|
|
144
145
|
}
|
|
145
146
|
};
|
|
146
147
|
// TODO: this is just a placeholder, we need to replace with an actually informative and accurate title (cc @metalmatze)
|
|
147
|
-
const profileSourceString = profileSource?.toString();
|
|
148
|
+
const profileSourceString = profileSource?.toString(timezone);
|
|
148
149
|
const hasProfileSource = profileSource !== undefined && profileSourceString !== '';
|
|
149
150
|
const headerParts = profileSourceString?.split('"') ?? [];
|
|
150
151
|
const compareMode = compare === true ||
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.360",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@parca/client": "^0.16.107",
|
|
7
|
-
"@parca/components": "^0.16.
|
|
7
|
+
"@parca/components": "^0.16.266",
|
|
8
8
|
"@parca/dynamicsize": "^0.16.61",
|
|
9
|
-
"@parca/hooks": "^0.0.
|
|
9
|
+
"@parca/hooks": "^0.0.47",
|
|
10
10
|
"@parca/parser": "^0.16.69",
|
|
11
|
-
"@parca/store": "^0.16.
|
|
12
|
-
"@parca/utilities": "^0.0.
|
|
11
|
+
"@parca/store": "^0.16.136",
|
|
12
|
+
"@parca/utilities": "^0.0.64",
|
|
13
13
|
"@tanstack/react-query": "^4.0.5",
|
|
14
14
|
"@types/react-beautiful-dnd": "^13.1.8",
|
|
15
15
|
"apache-arrow": "^12.0.0",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"access": "public",
|
|
51
51
|
"registry": "https://registry.npmjs.org/"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "6430a8027b0edb84336feea5c774e409595f40a6"
|
|
54
54
|
}
|
|
@@ -18,11 +18,10 @@ import type {VirtualElement} from '@popperjs/core';
|
|
|
18
18
|
import {usePopper} from 'react-popper';
|
|
19
19
|
|
|
20
20
|
import {Label} from '@parca/client';
|
|
21
|
-
import {TextWithTooltip} from '@parca/components';
|
|
22
|
-
import {formatDate, valueFormatter} from '@parca/utilities';
|
|
21
|
+
import {TextWithTooltip, useParcaContext} from '@parca/components';
|
|
22
|
+
import {formatDate, timePattern, valueFormatter} from '@parca/utilities';
|
|
23
23
|
|
|
24
24
|
import {HighlightedSeries} from '../';
|
|
25
|
-
import {timeFormat} from '../../';
|
|
26
25
|
|
|
27
26
|
interface Props {
|
|
28
27
|
x: number;
|
|
@@ -69,6 +68,8 @@ const MetricsTooltip = ({
|
|
|
69
68
|
sampleUnit,
|
|
70
69
|
delta,
|
|
71
70
|
}: Props): JSX.Element => {
|
|
71
|
+
const {timezone} = useParcaContext();
|
|
72
|
+
|
|
72
73
|
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
|
73
74
|
|
|
74
75
|
const {styles, attributes, ...popperProps} = usePopper(virtualElement, popperElement, {
|
|
@@ -154,7 +155,13 @@ const MetricsTooltip = ({
|
|
|
154
155
|
)}
|
|
155
156
|
<tr>
|
|
156
157
|
<td className="w-1/4">At</td>
|
|
157
|
-
<td className="w-3/4">
|
|
158
|
+
<td className="w-3/4">
|
|
159
|
+
{formatDate(
|
|
160
|
+
highlighted.timestamp,
|
|
161
|
+
timePattern(timezone as string),
|
|
162
|
+
timezone
|
|
163
|
+
)}
|
|
164
|
+
</td>
|
|
158
165
|
</tr>
|
|
159
166
|
</tbody>
|
|
160
167
|
</table>
|
|
@@ -19,7 +19,7 @@ import throttle from 'lodash.throttle';
|
|
|
19
19
|
import {useContextMenu} from 'react-contexify';
|
|
20
20
|
|
|
21
21
|
import {Label, MetricsSample, MetricsSeries as MetricsSeriesPb} from '@parca/client';
|
|
22
|
-
import {DateTimeRange} from '@parca/components';
|
|
22
|
+
import {DateTimeRange, useParcaContext} from '@parca/components';
|
|
23
23
|
import {
|
|
24
24
|
formatDate,
|
|
25
25
|
formatForTimespan,
|
|
@@ -132,6 +132,7 @@ export const RawMetricsGraph = ({
|
|
|
132
132
|
margin = 0,
|
|
133
133
|
sampleUnit,
|
|
134
134
|
}: Props): JSX.Element => {
|
|
135
|
+
const {timezone} = useParcaContext();
|
|
135
136
|
const graph = useRef(null);
|
|
136
137
|
const [dragging, setDragging] = useState(false);
|
|
137
138
|
const [hovering, setHovering] = useState(false);
|
|
@@ -537,7 +538,7 @@ export const RawMetricsGraph = ({
|
|
|
537
538
|
>
|
|
538
539
|
<line y2={6} className="stroke-gray-300 dark:stroke-gray-500" />
|
|
539
540
|
<text fill="currentColor" dy=".71em" y={9}>
|
|
540
|
-
{formatDate(d, formatForTimespan(from, to))}
|
|
541
|
+
{formatDate(d, formatForTimespan(from, to), timezone)}
|
|
541
542
|
</text>
|
|
542
543
|
</g>
|
|
543
544
|
<g key={`grid-${i}`}>
|
package/src/ProfileSource.tsx
CHANGED
|
@@ -27,8 +27,7 @@ export interface ProfileSource {
|
|
|
27
27
|
QueryRequest: () => QueryRequest;
|
|
28
28
|
ProfileType: () => ProfileType;
|
|
29
29
|
DiffSelection: () => ProfileDiffSelection;
|
|
30
|
-
|
|
31
|
-
toString: () => string;
|
|
30
|
+
toString: (timezone?: string) => string;
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
export interface ProfileSelection {
|
|
@@ -37,8 +36,13 @@ export interface ProfileSelection {
|
|
|
37
36
|
ProfileSource: () => ProfileSource;
|
|
38
37
|
Type: () => string;
|
|
39
38
|
}
|
|
39
|
+
const timeFormat = (timezone?: string): string => {
|
|
40
|
+
if (timezone !== undefined) {
|
|
41
|
+
return 'yyyy-MM-dd HH:mm:ss';
|
|
42
|
+
}
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
return "yyyy-MM-dd HH:mm:ss '(UTC)'";
|
|
45
|
+
};
|
|
42
46
|
|
|
43
47
|
export function ParamsString(params: {[key: string]: string}): string {
|
|
44
48
|
return Object.keys(params)
|
|
@@ -229,25 +233,17 @@ export class MergedProfileSource implements ProfileSource {
|
|
|
229
233
|
return ProfileType.fromString(Query.parse(this.query.toString()).profileName());
|
|
230
234
|
}
|
|
231
235
|
|
|
232
|
-
Describe(): JSX.Element {
|
|
233
|
-
return (
|
|
234
|
-
<a>
|
|
235
|
-
Merge of "{this.query.toString()}" from {formatDate(this.mergeFrom, timeFormat)}{' '}
|
|
236
|
-
to {formatDate(this.mergeTo, timeFormat)}
|
|
237
|
-
</a>
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
236
|
stringMatchers(): string[] {
|
|
242
237
|
return this.query.matchers
|
|
243
238
|
.filter((m: Matcher) => m.key !== '__name__')
|
|
244
239
|
.map((m: Matcher) => `${m.key}=${m.value}`);
|
|
245
240
|
}
|
|
246
241
|
|
|
247
|
-
toString(): string {
|
|
242
|
+
toString(timezone?: string): string {
|
|
248
243
|
return `merged profiles of query "${this.query.toString()}" from ${formatDate(
|
|
249
244
|
this.mergeFrom,
|
|
250
|
-
timeFormat
|
|
251
|
-
|
|
245
|
+
timeFormat(timezone),
|
|
246
|
+
timezone
|
|
247
|
+
)} to ${formatDate(this.mergeTo, timeFormat(timezone), timezone)}`;
|
|
252
248
|
}
|
|
253
249
|
}
|
|
@@ -132,6 +132,7 @@ export const ProfileView = ({
|
|
|
132
132
|
pprofDownloading,
|
|
133
133
|
compare,
|
|
134
134
|
}: ProfileViewProps): JSX.Element => {
|
|
135
|
+
const {timezone} = useParcaContext();
|
|
135
136
|
const {ref, dimensions} = useContainerDimensions();
|
|
136
137
|
const [curPath, setCurPath] = useState<string[]>([]);
|
|
137
138
|
const [rawDashboardItems = ['icicle'], setDashboardItems] = useURLState({
|
|
@@ -325,7 +326,7 @@ export const ProfileView = ({
|
|
|
325
326
|
};
|
|
326
327
|
|
|
327
328
|
// TODO: this is just a placeholder, we need to replace with an actually informative and accurate title (cc @metalmatze)
|
|
328
|
-
const profileSourceString = profileSource?.toString();
|
|
329
|
+
const profileSourceString = profileSource?.toString(timezone);
|
|
329
330
|
const hasProfileSource = profileSource !== undefined && profileSourceString !== '';
|
|
330
331
|
const headerParts = profileSourceString?.split('"') ?? [];
|
|
331
332
|
|