Compare commits

..

12 Commits

Author SHA1 Message Date
Abhi kumar
703b221dfe Merge branch 'main' into chore/base-config-builder 2026-02-10 22:28:27 +05:30
Abhi Kumar
9f13086214 chore: removed dayjs extention 2026-02-10 22:23:33 +05:30
Vishal Sharma
a3bd72ad86 feat(onboarding): add Docker support for apm data sources, Convex and simplify PHP flow (#10261)
Some checks are pending
build-staging / prepare (push) Waiting to run
build-staging / js-build (push) Blocked by required conditions
build-staging / go-build (push) Blocked by required conditions
build-staging / staging (push) Blocked by required conditions
Release Drafter / update_release_draft (push) Waiting to run
* feat(onboarding): add Docker support for apm data sources, Convex and simplify PHP flow

- Add Convex logo asset for integration branding
- Add Docker deployment options for Java frameworks (Spring Boot, Tomcat, JBoss, Quarkus)
- Update JBoss configuration to include WildFly support and associated keywords
- Restructure PHP onboarding flow to prioritize environment selection over framework
- Update Java keywords to include JDBC and remove deprecated metrics tag

* chore: remove 'angular' from related keywords in the onboarding configuration
2026-02-10 18:23:24 +05:30
Nikhil Soni
786070d90b refactor: switch group by instead of triggering aggregation (#10263)
Using FINAL in clickhouse query will trigger the aggregation
merge of data while using group by will be more efficient.
It's recommended id docs as well - https://clickhouse.com/
docs/engines/table-engines/mergetree-family/
aggregatingmergetree#select-and-insert
2026-02-10 12:35:31 +00:00
Abhi kumar
20e58db10d Merge branch 'main' into chore/base-config-builder 2026-02-10 16:54:27 +05:30
Abhi Kumar
974bfcd732 chore: added different tooltips 2026-02-10 16:53:49 +05:30
Abhi Kumar
e6d89465da fix: pr review changes 2026-02-10 16:05:04 +05:30
Abhi Kumar
a634ae9b66 fix: pr review changes 2026-02-10 15:48:29 +05:30
Abhi Kumar
bb1f5ba29f chore: tsc fix 2026-02-10 13:31:47 +05:30
Abhi Kumar
30b3a68154 Merge branch 'main' of https://github.com/SigNoz/signoz into chore/base-config-builder 2026-02-10 12:57:31 +05:30
Abhi Kumar
08aa8759ba chore: added a common chart wrapper 2026-02-10 12:57:02 +05:30
Abhi Kumar
c941233723 chore: refactored the config builder and added base config builder 2026-02-09 21:34:08 +05:30
16 changed files with 581 additions and 651 deletions

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="184" height="188" fill="none" viewBox="0 0 184 188"><path fill="#f3b01c" d="M108.092 130.021c18.166-2.018 35.293-11.698 44.723-27.854-4.466 39.961-48.162 65.218-83.83 49.711-3.286-1.425-6.115-3.796-8.056-6.844-8.016-12.586-10.65-28.601-6.865-43.135 10.817 18.668 32.81 30.111 54.028 28.122"/><path fill="#8d2676" d="M53.401 90.174c-7.364 17.017-7.682 36.94 1.345 53.336-31.77-23.902-31.423-75.052-.388-98.715 2.87-2.187 6.282-3.485 9.86-3.683 14.713-.776 29.662 4.91 40.146 15.507-21.3.212-42.046 13.857-50.963 33.555"/><path fill="#ee342f" d="M114.637 61.855C103.89 46.87 87.069 36.668 68.639 36.358c35.625-16.17 79.446 10.047 84.217 48.807.444 3.598-.139 7.267-1.734 10.512-6.656 13.518-18.998 24.002-33.42 27.882 10.567-19.599 9.263-43.544-3.065-61.704"/></svg>

After

Width:  |  Height:  |  Size: 811 B

View File

@@ -0,0 +1,91 @@
import { useCallback, useRef } from 'react';
import ChartLayout from 'container/DashboardContainer/visualization/layout/ChartLayout/ChartLayout';
import Legend from 'lib/uPlotV2/components/Legend/Legend';
import { LegendPosition } from 'lib/uPlotV2/components/types';
import UPlotChart from 'lib/uPlotV2/components/UPlotChart';
import { PlotContextProvider } from 'lib/uPlotV2/context/PlotContext';
import TooltipPlugin from 'lib/uPlotV2/plugins/TooltipPlugin/TooltipPlugin';
import noop from 'lodash-es/noop';
import uPlot from 'uplot';
import { ChartProps } from '../types';
const TOOLTIP_WIDTH_PADDING = 60;
const TOOLTIP_MIN_WIDTH = 200;
export default function ChartWrapper({
legendConfig = { position: LegendPosition.BOTTOM },
config,
data,
width: containerWidth,
height: containerHeight,
showTooltip = true,
canPinTooltip = false,
syncMode,
syncKey,
onDestroy = noop,
children,
layoutChildren,
renderTooltip,
'data-testid': testId,
}: ChartProps): JSX.Element {
const plotInstanceRef = useRef<uPlot | null>(null);
const legendComponent = useCallback(
(averageLegendWidth: number): React.ReactNode => {
return (
<Legend
config={config}
position={legendConfig.position}
averageLegendWidth={averageLegendWidth}
/>
);
},
[config, legendConfig.position],
);
return (
<PlotContextProvider>
<ChartLayout
config={config}
containerWidth={containerWidth}
containerHeight={containerHeight}
legendConfig={legendConfig}
legendComponent={legendComponent}
layoutChildren={layoutChildren}
>
{({ chartWidth, chartHeight, averageLegendWidth }): JSX.Element => (
<UPlotChart
config={config}
data={data}
width={chartWidth}
height={chartHeight}
plotRef={(plot): void => {
plotInstanceRef.current = plot;
}}
onDestroy={(plot: uPlot): void => {
plotInstanceRef.current = null;
onDestroy(plot);
}}
data-testid={testId}
>
{children}
{showTooltip && (
<TooltipPlugin
config={config}
canPinTooltip={canPinTooltip}
syncMode={syncMode}
maxWidth={Math.max(
TOOLTIP_MIN_WIDTH,
averageLegendWidth + TOOLTIP_WIDTH_PADDING,
)}
syncKey={syncKey}
render={renderTooltip}
/>
)}
</UPlotChart>
)}
</ChartLayout>
</PlotContextProvider>
);
}

View File

@@ -1,104 +1,32 @@
import { useCallback, useRef } from 'react';
import ChartLayout from 'container/DashboardContainer/visualization/layout/ChartLayout/ChartLayout';
import Legend from 'lib/uPlotV2/components/Legend/Legend';
import Tooltip from 'lib/uPlotV2/components/Tooltip/Tooltip';
import { useCallback } from 'react';
import ChartWrapper from 'container/DashboardContainer/visualization/charts/ChartWrapper/ChartWrapper';
import TimeSeriesTooltip from 'lib/uPlotV2/components/Tooltip/TimeSeriesTooltip';
import {
LegendPosition,
TimeSeriesTooltipProps,
TooltipRenderArgs,
} from 'lib/uPlotV2/components/types';
import UPlotChart from 'lib/uPlotV2/components/UPlotChart';
import { PlotContextProvider } from 'lib/uPlotV2/context/PlotContext';
import TooltipPlugin from 'lib/uPlotV2/plugins/TooltipPlugin/TooltipPlugin';
import _noop from 'lodash-es/noop';
import uPlot from 'uplot';
import { ChartProps } from '../types';
import { TimeSeriesChartProps } from '../types';
const TOOLTIP_WIDTH_PADDING = 60;
const TOOLTIP_MIN_WIDTH = 200;
export default function TimeSeries(props: TimeSeriesChartProps): JSX.Element {
const { children, ...rest } = props;
export default function TimeSeries({
legendConfig = { position: LegendPosition.BOTTOM },
config,
data,
width: containerWidth,
height: containerHeight,
disableTooltip = false,
canPinTooltip = false,
timezone,
yAxisUnit,
decimalPrecision,
syncMode,
syncKey,
onDestroy = _noop,
children,
layoutChildren,
'data-testid': testId,
}: ChartProps): JSX.Element {
const plotInstanceRef = useRef<uPlot | null>(null);
const legendComponent = useCallback(
(averageLegendWidth: number): React.ReactNode => {
return (
<Legend
config={config}
position={legendConfig.position}
averageLegendWidth={averageLegendWidth}
/>
);
const renderTooltip = useCallback(
(props: TooltipRenderArgs): React.ReactNode => {
const tooltipProps: TimeSeriesTooltipProps = {
...props,
timezone: rest.timezone,
yAxisUnit: rest.yAxisUnit,
decimalPrecision: rest.decimalPrecision,
};
return <TimeSeriesTooltip {...tooltipProps} />;
},
[config, legendConfig.position],
[rest.timezone, rest.yAxisUnit, rest.decimalPrecision],
);
return (
<PlotContextProvider>
<ChartLayout
config={config}
containerWidth={containerWidth}
containerHeight={containerHeight}
legendConfig={legendConfig}
legendComponent={legendComponent}
layoutChildren={layoutChildren}
>
{({ chartWidth, chartHeight, averageLegendWidth }): JSX.Element => (
<UPlotChart
config={config}
data={data}
width={chartWidth}
height={chartHeight}
plotRef={(plot): void => {
plotInstanceRef.current = plot;
}}
onDestroy={(plot: uPlot): void => {
plotInstanceRef.current = null;
onDestroy(plot);
}}
data-testid={testId}
>
{children}
{!disableTooltip && (
<TooltipPlugin
config={config}
canPinTooltip={canPinTooltip}
syncMode={syncMode}
maxWidth={Math.max(
TOOLTIP_MIN_WIDTH,
averageLegendWidth + TOOLTIP_WIDTH_PADDING,
)}
syncKey={syncKey}
render={(props: TooltipRenderArgs): React.ReactNode => (
<Tooltip
{...props}
timezone={timezone}
yAxisUnit={yAxisUnit}
decimalPrecision={decimalPrecision}
/>
)}
/>
)}
</UPlotChart>
)}
</ChartLayout>
</PlotContextProvider>
<ChartWrapper {...rest} renderTooltip={renderTooltip}>
{children}
</ChartWrapper>
);
}

View File

@@ -1,29 +1,40 @@
import { PrecisionOption } from 'components/Graph/types';
import { LegendConfig } from 'lib/uPlotV2/components/types';
import { LegendConfig, TooltipRenderArgs } from 'lib/uPlotV2/components/types';
import { UPlotConfigBuilder } from 'lib/uPlotV2/config/UPlotConfigBuilder';
import { DashboardCursorSync } from 'lib/uPlotV2/plugins/TooltipPlugin/types';
interface BaseChartProps {
width: number;
height: number;
disableTooltip?: boolean;
showTooltip?: boolean;
timezone: string;
syncMode?: DashboardCursorSync;
syncKey?: string;
canPinTooltip?: boolean;
yAxisUnit?: string;
decimalPrecision?: PrecisionOption;
'data-testid'?: string;
}
interface TimeSeriesChartProps extends BaseChartProps {
interface UPlotBasedChartProps {
config: UPlotConfigBuilder;
legendConfig: LegendConfig;
data: uPlot.AlignedData;
syncMode?: DashboardCursorSync;
syncKey?: string;
plotRef?: (plot: uPlot | null) => void;
onDestroy?: (plot: uPlot) => void;
children?: React.ReactNode;
layoutChildren?: React.ReactNode;
'data-testid'?: string;
}
export type ChartProps = TimeSeriesChartProps;
export interface TimeSeriesChartProps
extends BaseChartProps,
UPlotBasedChartProps {
legendConfig: LegendConfig;
}
export interface BarChartProps extends BaseChartProps, UPlotBasedChartProps {
legendConfig: LegendConfig;
isStackedBarChart?: boolean;
}
export type ChartProps = (TimeSeriesChartProps | BarChartProps) & {
renderTooltip: (props: TooltipRenderArgs) => React.ReactNode;
};

View File

@@ -6,7 +6,6 @@ import { PanelWrapperProps } from 'container/PanelWrapper/panelWrapper.types';
import { useIsDarkMode } from 'hooks/useDarkMode';
import { useResizeObserver } from 'hooks/useDimensions';
import { LegendPosition } from 'lib/uPlotV2/components/types';
import { LineInterpolation } from 'lib/uPlotV2/config/types';
import { ContextMenu } from 'periscope/components/ContextMenu';
import { useDashboard } from 'providers/Dashboard/Dashboard';
import { useTimezone } from 'providers/Timezone';
@@ -73,55 +72,28 @@ function TimeSeriesPanel(props: PanelWrapperProps): JSX.Element {
}, [queryResponse?.data?.payload]);
const config = useMemo(() => {
const tzDate = (timestamp: number): Date =>
uPlot.tzDate(new Date(timestamp * 1e3), timezone.value);
return prepareUPlotConfig({
widgetId: widget.id || '',
apiResponse: queryResponse?.data?.payload as MetricRangePayloadProps,
tzDate,
minTimeScale: minTimeScale,
maxTimeScale: maxTimeScale,
isLogScale: widget?.isLogScale ?? false,
thresholds: {
scaleKey: 'y',
thresholds: (widget.thresholds || []).map((threshold) => ({
thresholdValue: threshold.thresholdValue ?? 0,
thresholdColor: threshold.thresholdColor,
thresholdUnit: threshold.thresholdUnit,
thresholdLabel: threshold.thresholdLabel,
})),
yAxisUnit: widget.yAxisUnit,
},
yAxisUnit: widget.yAxisUnit || '',
softMin: widget.softMin === undefined ? null : widget.softMin,
softMax: widget.softMax === undefined ? null : widget.softMax,
spanGaps: false,
colorMapping: widget.customLegendColors ?? {},
lineInterpolation: LineInterpolation.Spline,
widget,
isDarkMode,
currentQuery: widget.query,
onClick: clickHandlerWithContextMenu,
onDragSelect,
currentQuery: widget.query,
apiResponse: queryResponse?.data?.payload as MetricRangePayloadProps,
timezone,
panelMode,
minTimeScale: minTimeScale,
maxTimeScale: maxTimeScale,
});
}, [
widget.id,
maxTimeScale,
minTimeScale,
timezone.value,
widget.customLegendColors,
widget.isLogScale,
widget.softMax,
widget.softMin,
widget,
isDarkMode,
queryResponse?.data?.payload,
widget.query,
widget.thresholds,
widget.yAxisUnit,
panelMode,
clickHandlerWithContextMenu,
onDragSelect,
queryResponse?.data?.payload,
panelMode,
minTimeScale,
maxTimeScale,
timezone,
]);
const layoutChildren = useMemo(() => {

View File

@@ -1,3 +1,4 @@
import { Timezone } from 'components/CustomTimePicker/timezoneUtils';
import { PANEL_TYPES } from 'constants/queryBuilder';
import {
fillMissingXAxisTimestamps,
@@ -5,23 +6,20 @@ import {
} from 'container/DashboardContainer/visualization/panels/utils';
import { getLegend } from 'lib/dashboard/getQueryResults';
import getLabelName from 'lib/getLabelName';
import onClickPlugin, {
OnClickPluginOpts,
} from 'lib/uPlotLib/plugins/onClickPlugin';
import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin';
import {
DistributionType,
DrawStyle,
LineInterpolation,
LineStyle,
SelectionPreferencesSource,
VisibilityMode,
} from 'lib/uPlotV2/config/types';
import { UPlotConfigBuilder } from 'lib/uPlotV2/config/UPlotConfigBuilder';
import { ThresholdsDrawHookOptions } from 'lib/uPlotV2/hooks/types';
import { Widgets } from 'types/api/dashboard/getAll';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { PanelMode } from '../types';
import { buildBaseConfig } from '../utils/baseConfigBuilder';
export const prepareChartData = (
apiResponse: MetricRangePayloadProps,
@@ -34,112 +32,39 @@ export const prepareChartData = (
};
export const prepareUPlotConfig = ({
widgetId,
apiResponse,
tzDate,
minTimeScale,
maxTimeScale,
isLogScale,
thresholds,
softMin,
softMax,
spanGaps,
colorMapping,
lineInterpolation,
widget,
isDarkMode,
currentQuery,
onDragSelect,
onClick,
yAxisUnit,
onDragSelect,
apiResponse,
timezone,
panelMode,
minTimeScale,
maxTimeScale,
}: {
widgetId: string;
apiResponse: MetricRangePayloadProps;
tzDate: uPlot.LocalDateFromUnix;
minTimeScale: number | undefined;
maxTimeScale: number | undefined;
isLogScale: boolean;
softMin: number | null;
softMax: number | null;
spanGaps: boolean;
colorMapping: Record<string, string>;
lineInterpolation: LineInterpolation;
widget: Widgets;
isDarkMode: boolean;
thresholds: ThresholdsDrawHookOptions;
currentQuery: Query;
yAxisUnit: string;
onClick: OnClickPluginOpts['onClick'];
onDragSelect: (startTime: number, endTime: number) => void;
onClick?: OnClickPluginOpts['onClick'];
apiResponse: MetricRangePayloadProps;
timezone: Timezone;
panelMode: PanelMode;
minTimeScale?: number;
maxTimeScale?: number;
}): UPlotConfigBuilder => {
const builder = new UPlotConfigBuilder({
const builder = buildBaseConfig({
widget,
isDarkMode,
onClick,
onDragSelect,
widgetId,
tzDate,
shouldSaveSelectionPreference: panelMode === PanelMode.DASHBOARD_VIEW,
selectionPreferencesSource: [
PanelMode.DASHBOARD_VIEW,
PanelMode.STANDALONE_VIEW,
].includes(panelMode)
? SelectionPreferencesSource.LOCAL_STORAGE
: SelectionPreferencesSource.IN_MEMORY,
});
// X scale time axis
builder.addScale({
scaleKey: 'x',
time: true,
min: minTimeScale,
max: maxTimeScale,
logBase: isLogScale ? 10 : undefined,
distribution: isLogScale
? DistributionType.Logarithmic
: DistributionType.Linear,
});
// Y scale value axis, driven primarily by softMin/softMax and data
builder.addScale({
scaleKey: 'y',
time: false,
min: undefined,
max: undefined,
softMin: softMin ?? undefined,
softMax: softMax ?? undefined,
thresholds,
logBase: isLogScale ? 10 : undefined,
distribution: isLogScale
? DistributionType.Logarithmic
: DistributionType.Linear,
});
builder.addThresholds(thresholds);
if (typeof onClick === 'function') {
builder.addPlugin(
onClickPlugin({
onClick,
apiResponse,
}),
);
}
builder.addAxis({
scaleKey: 'x',
show: true,
side: 2,
isDarkMode,
isLogScale: false,
panelType: PANEL_TYPES.TIME_SERIES,
});
builder.addAxis({
scaleKey: 'y',
show: true,
side: 3,
isDarkMode,
isLogScale: false,
yAxisUnit,
apiResponse,
timezone,
panelMode,
panelType: PANEL_TYPES.TIME_SERIES,
minTimeScale,
maxTimeScale,
});
apiResponse.data?.result?.forEach((series) => {
@@ -157,14 +82,16 @@ export const prepareUPlotConfig = ({
scaleKey: 'y',
drawStyle: DrawStyle.Line,
label: label,
colorMapping,
spanGaps,
colorMapping: widget.customLegendColors ?? {},
spanGaps: false,
lineStyle: LineStyle.Solid,
lineInterpolation,
lineInterpolation: LineInterpolation.Spline,
showPoints: VisibilityMode.Never,
pointSize: 5,
isDarkMode,
panelType: PANEL_TYPES.TIME_SERIES,
});
});
return builder;
};

View File

@@ -0,0 +1,127 @@
import { Timezone } from 'components/CustomTimePicker/timezoneUtils';
import { PANEL_TYPES } from 'constants/queryBuilder';
import onClickPlugin, {
OnClickPluginOpts,
} from 'lib/uPlotLib/plugins/onClickPlugin';
import {
DistributionType,
SelectionPreferencesSource,
} from 'lib/uPlotV2/config/types';
import { UPlotConfigBuilder } from 'lib/uPlotV2/config/UPlotConfigBuilder';
import { ThresholdsDrawHookOptions } from 'lib/uPlotV2/hooks/types';
import { Widgets } from 'types/api/dashboard/getAll';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import uPlot from 'uplot';
import { PanelMode } from '../types';
export interface BaseConfigBuilderProps {
widget: Widgets;
apiResponse: MetricRangePayloadProps;
isDarkMode: boolean;
onClick: OnClickPluginOpts['onClick'];
onDragSelect: (startTime: number, endTime: number) => void;
timezone: Timezone;
panelMode: PanelMode;
panelType: PANEL_TYPES;
minTimeScale?: number;
maxTimeScale?: number;
}
export function buildBaseConfig({
widget,
isDarkMode,
onClick,
onDragSelect,
apiResponse,
timezone,
panelMode,
panelType,
minTimeScale,
maxTimeScale,
}: BaseConfigBuilderProps): UPlotConfigBuilder {
const tzDate = (timestamp: number): Date =>
uPlot.tzDate(new Date(timestamp * 1e3), timezone.value);
const builder = new UPlotConfigBuilder({
onDragSelect,
widgetId: widget.id,
tzDate,
shouldSaveSelectionPreference: panelMode === PanelMode.DASHBOARD_VIEW,
selectionPreferencesSource: [
PanelMode.DASHBOARD_VIEW,
PanelMode.STANDALONE_VIEW,
].includes(panelMode)
? SelectionPreferencesSource.LOCAL_STORAGE
: SelectionPreferencesSource.IN_MEMORY,
});
const thresholdOptions: ThresholdsDrawHookOptions = {
scaleKey: 'y',
thresholds: (widget.thresholds || []).map((threshold) => ({
thresholdValue: threshold.thresholdValue ?? 0,
thresholdColor: threshold.thresholdColor,
thresholdUnit: threshold.thresholdUnit,
thresholdLabel: threshold.thresholdLabel,
})),
yAxisUnit: widget.yAxisUnit,
};
builder.addThresholds(thresholdOptions);
builder.addScale({
scaleKey: 'x',
time: true,
min: minTimeScale,
max: maxTimeScale,
logBase: widget.isLogScale ? 10 : undefined,
distribution: widget.isLogScale
? DistributionType.Logarithmic
: DistributionType.Linear,
});
// Y scale value axis, driven primarily by softMin/softMax and data
builder.addScale({
scaleKey: 'y',
time: false,
min: undefined,
max: undefined,
softMin: widget.softMin ?? undefined,
softMax: widget.softMax ?? undefined,
// thresholds,
logBase: widget.isLogScale ? 10 : undefined,
distribution: widget.isLogScale
? DistributionType.Logarithmic
: DistributionType.Linear,
});
if (typeof onClick === 'function') {
builder.addPlugin(
onClickPlugin({
onClick,
apiResponse,
}),
);
}
builder.addAxis({
scaleKey: 'x',
show: true,
side: 2,
isDarkMode,
isLogScale: widget.isLogScale,
panelType,
});
builder.addAxis({
scaleKey: 'y',
show: true,
side: 3,
isDarkMode,
isLogScale: widget.isLogScale,
yAxisUnit: widget.yAxisUnit,
panelType,
});
return builder;
}

View File

@@ -323,7 +323,6 @@
"java instrumentation",
"java k8s",
"java logs",
"java metrics",
"java microservices",
"java monitoring",
"java observability",
@@ -332,10 +331,12 @@
"java vm",
"java windows",
"jboss",
"wildfly",
"jdk 11",
"jdk 17",
"jdk 21",
"jdk 8",
"jdbc",
"opentelemetry java",
"quarkus",
"spring boot",
@@ -372,6 +373,12 @@
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-springboot/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-springboot/"
},
{
"key": "windows",
"label": "Windows",
@@ -403,6 +410,12 @@
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-tomcat/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-tomcat/"
},
{
"key": "windows",
"label": "Windows",
@@ -414,7 +427,7 @@
},
{
"key": "jboss",
"label": "JBoss",
"label": "JBoss/WildFly",
"imgUrl": "/Logos/jboss.svg",
"link": "/docs/instrumentation/opentelemetry-jboss/",
"question": {
@@ -434,6 +447,12 @@
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-jboss/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-jboss/"
},
{
"key": "windows",
"label": "Windows",
@@ -465,6 +484,12 @@
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-quarkus/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-quarkus/"
},
{
"key": "windows",
"label": "Windows",
@@ -495,6 +520,18 @@
"label": "Kubernetes",
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-java/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-java/"
},
{
"key": "windows",
"label": "Windows",
"imgUrl": "/Logos/windows.svg",
"link": "/docs/instrumentation/opentelemetry-java/"
}
]
}
@@ -530,7 +567,6 @@
"python in containers",
"python instrumentation",
"python k8s",
"python metrics",
"python microservices",
"python observability",
"python on kubernetes",
@@ -583,7 +619,6 @@
],
"module": "apm",
"relatedSearchKeywords": [
"angular",
"apm",
"apm/traces",
"application performance monitoring",
@@ -595,7 +630,6 @@
"next.js",
"nodejs",
"nuxtjs",
"reactjs",
"traces",
"tracing",
"ts",
@@ -610,8 +644,8 @@
"entityID": "framework",
"options": [
{
"key": "nodejs",
"label": "NodeJs",
"key": "nodejs-nestjs",
"label": "NodeJs/NestJS",
"imgUrl": "/Logos/nodejs.svg",
"link": "/docs/instrumentation/opentelemetry-javascript/",
"question": {
@@ -631,6 +665,12 @@
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-javascript/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-javascript/"
},
{
"key": "windows",
"label": "Windows",
@@ -640,99 +680,6 @@
]
}
},
{
"key": "express",
"label": "Express",
"imgUrl": "/Logos/express.svg",
"link": "/docs/instrumentation/opentelemetry-express/",
"question": {
"desc": "What is your Environment?",
"type": "select",
"entityID": "environment",
"options": [
{
"key": "vm",
"label": "VM",
"imgUrl": "/Logos/vm.svg",
"link": "/docs/instrumentation/opentelemetry-express/"
},
{
"key": "k8s",
"label": "Kubernetes",
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-express/"
},
{
"key": "windows",
"label": "Windows",
"imgUrl": "/Logos/windows.svg",
"link": "/docs/instrumentation/opentelemetry-express/"
}
]
}
},
{
"key": "nestjs",
"label": "NestJS",
"imgUrl": "/Logos/nestjs.svg",
"link": "/docs/instrumentation/opentelemetry-nestjs/",
"question": {
"desc": "What is your Environment?",
"type": "select",
"entityID": "environment",
"options": [
{
"key": "vm",
"label": "VM",
"imgUrl": "/Logos/vm.svg",
"link": "/docs/instrumentation/opentelemetry-nestjs/"
},
{
"key": "k8s",
"label": "Kubernetes",
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-nestjs/"
},
{
"key": "windows",
"label": "Windows",
"imgUrl": "/Logos/windows.svg",
"link": "/docs/instrumentation/opentelemetry-nestjs/"
}
]
}
},
{
"key": "angular",
"label": "Angular",
"imgUrl": "/Logos/angular.svg",
"link": "/docs/instrumentation/opentelemetry-angular/",
"question": {
"desc": "What is your Environment?",
"type": "select",
"entityID": "environment",
"options": [
{
"key": "vm",
"label": "VM",
"imgUrl": "/Logos/vm.svg",
"link": "/docs/instrumentation/opentelemetry-angular/"
},
{
"key": "k8s",
"label": "Kubernetes",
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-angular/"
},
{
"key": "windows",
"label": "Windows",
"imgUrl": "/Logos/windows.svg",
"link": "/docs/instrumentation/opentelemetry-angular/"
}
]
}
},
{
"key": "nextjs",
"label": "NextJS",
@@ -755,6 +702,12 @@
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-nextjs/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-nextjs/"
},
{
"key": "windows",
"label": "Windows",
@@ -764,37 +717,6 @@
]
}
},
{
"key": "reactjs",
"label": "ReactJS",
"imgUrl": "/Logos/reactjs.svg",
"link": "/docs/instrumentation/opentelemetry-reactjs/",
"question": {
"desc": "What is your Environment?",
"type": "select",
"entityID": "environment",
"options": [
{
"key": "vm",
"label": "VM",
"imgUrl": "/Logos/vm.svg",
"link": "/docs/instrumentation/opentelemetry-reactjs/"
},
{
"key": "k8s",
"label": "Kubernetes",
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-reactjs/"
},
{
"key": "windows",
"label": "Windows",
"imgUrl": "/Logos/windows.svg",
"link": "/docs/instrumentation/opentelemetry-reactjs/"
}
]
}
},
{
"key": "nuxtjs",
"label": "NuxtJS",
@@ -817,6 +739,12 @@
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-nuxtjs/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-nuxtjs/"
},
{
"key": "windows",
"label": "Windows",
@@ -830,32 +758,7 @@
"key": "react-native",
"label": "React Native",
"imgUrl": "/Logos/reactjs.svg",
"link": "/docs/instrumentation/opentelemetry-react-native/",
"question": {
"desc": "What is your Environment?",
"type": "select",
"entityID": "environment",
"options": [
{
"key": "vm",
"label": "VM",
"imgUrl": "/Logos/vm.svg",
"link": "/docs/instrumentation/opentelemetry-react-native/"
},
{
"key": "k8s",
"label": "Kubernetes",
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-react-native/"
},
{
"key": "windows",
"label": "Windows",
"imgUrl": "/Logos/windows.svg",
"link": "/docs/instrumentation/opentelemetry-react-native/"
}
]
}
"link": "/docs/instrumentation/opentelemetry-react-native/"
}
]
}
@@ -889,7 +792,6 @@
"golang",
"golang apm",
"golang instrumentation",
"golang metrics",
"golang observability",
"golang performance monitoring",
"golang tracing",
@@ -980,69 +882,39 @@
"php-fpm monitoring",
"slim php",
"traces",
"tracing"
"tracing",
"wordpress"
],
"id": "php",
"link": "/docs/instrumentation/opentelemetry-php/",
"question": {
"desc": "Which PHP framework do you use?",
"desc": "What is your Environment?",
"type": "select",
"entityID": "framework",
"entityID": "environment",
"options": [
{
"key": "laravel",
"label": "Laravel",
"imgUrl": "/Logos/laravel.svg",
"link": "/docs/instrumentation/laravel/",
"question": {
"desc": "What is your Environment?",
"type": "select",
"entityID": "environment",
"options": [
{
"key": "vm",
"label": "VM",
"imgUrl": "/Logos/vm.svg",
"link": "/docs/instrumentation/laravel/"
},
{
"key": "k8s",
"label": "Kubernetes",
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/laravel/"
}
]
}
"key": "vm",
"label": "VM",
"imgUrl": "/Logos/vm.svg",
"link": "/docs/instrumentation/opentelemetry-php/"
},
{
"key": "Others",
"label": "Others",
"imgUrl": "/Logos/php-others.svg",
"link": "/docs/instrumentation/opentelemetry-php/",
"question": {
"desc": "What is your Environment?",
"type": "select",
"entityID": "environment",
"options": [
{
"key": "vm",
"label": "VM",
"imgUrl": "/Logos/vm.svg",
"link": "/docs/instrumentation/opentelemetry-php/"
},
{
"key": "k8s",
"label": "Kubernetes",
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-php/"
},
{
"key": "windows",
"label": "Windows",
"imgUrl": "/Logos/windows.svg",
"link": "/docs/instrumentation/opentelemetry-php/"
}
]
}
"key": "k8s",
"label": "Kubernetes",
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-php/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-php/"
},
{
"key": "windows",
"label": "Windows",
"imgUrl": "/Logos/windows.svg",
"link": "/docs/instrumentation/opentelemetry-php/"
}
]
}
@@ -1117,6 +989,12 @@
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-dotnet/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-dotnet/"
},
{
"key": "windows",
"label": "Windows",
@@ -1128,7 +1006,7 @@
},
{
"dataSource": "ruby-on-rails",
"label": "Ruby on Rails",
"label": "Ruby",
"imgUrl": "/Logos/ruby-on-rails.svg",
"tags": [
"apm/traces"
@@ -1168,9 +1046,12 @@
"ruby tracing",
"ruby-on-rails",
"traces",
"tracing"
"tracing",
"sinatra",
"sidekiq",
"resque"
],
"id": "ruby-on-rails",
"id": "ruby",
"link": "/docs/instrumentation/opentelemetry-ruby-on-rails/",
"question": {
"desc": "What is your Environment?",
@@ -1189,6 +1070,12 @@
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/instrumentation/opentelemetry-ruby-on-rails/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/instrumentation/opentelemetry-ruby-on-rails/"
},
{
"key": "windows",
"label": "Windows",
@@ -1468,41 +1355,6 @@
"id": "nginx-tracing",
"link": "/docs/instrumentation/opentelemetry-nginx/"
},
{
"dataSource": "opentelemetry-wordpress",
"label": "WordPress",
"imgUrl": "/Logos/wordpress.svg",
"tags": [
"apm/traces"
],
"module": "apm",
"relatedSearchKeywords": [
"apm",
"apm/traces",
"application performance monitoring",
"monitor wordpress site",
"opentelemetry",
"opentelemetry wordpress",
"opentelemetry-wordpress",
"otel",
"otel wordpress",
"traces",
"tracing",
"wordpress",
"wordpress apm",
"wordpress instrumentation",
"wordpress metrics",
"wordpress monitoring",
"wordpress observability",
"wordpress performance",
"wordpress php monitoring",
"wordpress plugin monitoring",
"wordpress to signoz",
"wordpress tracing"
],
"id": "opentelemetry-wordpress",
"link": "/docs/instrumentation/opentelemetry-wordpress/"
},
{
"dataSource": "opentelemetry-cloudflare",
"label": "Cloudflare Tracing",
@@ -1567,6 +1419,25 @@
"id": "opentelemetry-cloudflare-logs",
"link": "/docs/logs-management/send-logs/cloudflare-logs/"
},
{
"dataSource": "convex-logs",
"label": "Convex Logs",
"imgUrl": "/Logos/convex-logo.svg",
"tags": [
"logs"
],
"module": "logs",
"relatedSearchKeywords": [
"convex",
"convex log streaming",
"convex logs",
"convex webhook",
"logging",
"logs"
],
"id": "convex-logs",
"link": "/docs/logs-management/send-logs/convex-log-streams-signoz/"
},
{
"dataSource": "kubernetes-pod-logs",
"label": "Kubernetes Pod Logs",
@@ -4568,6 +4439,7 @@
],
"module": "metrics",
"relatedSearchKeywords": [
"browser metrics",
"core web vitals metrics",
"frontend metrics",
"frontend monitoring",
@@ -4587,7 +4459,7 @@
"svelte",
"sveltekit",
"nextjs",
"next.js"
"next.js"
],
"link": "/docs/frontend-monitoring/web-vitals-with-metrics/"
},
@@ -4622,7 +4494,7 @@
"svelte",
"sveltekit",
"nextjs",
"next.js"
"next.js"
],
"link": "/docs/frontend-monitoring/web-vitals-with-traces/"
},
@@ -4664,7 +4536,7 @@
"svelte",
"sveltekit",
"nextjs",
"next.js"
"next.js"
],
"link": "/docs/frontend-monitoring/document-load/"
},
@@ -5316,23 +5188,6 @@
],
"link": "/docs/metrics-management/mysql-metrics/"
},
{
"dataSource": "jvm",
"label": "JVM",
"imgUrl": "/Logos/java.svg",
"tags": [
"metrics"
],
"module": "metrics",
"relatedSearchKeywords": [
"java virtual machine",
"jvm",
"jvm metrics",
"jvm monitoring",
"runtime"
],
"link": "/docs/tutorial/jvm-metrics/"
},
{
"dataSource": "jmx",
"label": "JMX",
@@ -5348,7 +5203,7 @@
"jmx monitoring",
"runtime"
],
"link": "/docs/tutorial/jmx-metrics/"
"link": "/docs/metrics-management/send-metrics/applications/opentelemetry-java/jmx-metrics/"
},
{
"dataSource": "prometheus-metrics",
@@ -5574,16 +5429,17 @@
"svelte",
"sveltekit",
"nextjs",
"next.js"
"next.js"
],
"link": "/docs/frontend-monitoring/sending-logs-with-opentelemetry/"
},
{
"dataSource": "frontend-traces",
"label": "Frontend Traces",
"label": "Frontend Tracing",
"imgUrl": "/Logos/traces.svg",
"tags": [
"Frontend Monitoring"
"Frontend Monitoring",
"apm/traces"
],
"module": "apm",
"relatedSearchKeywords": [
@@ -5605,7 +5461,7 @@
"svelte",
"sveltekit",
"nextjs",
"next.js"
"next.js"
],
"link": "/docs/frontend-monitoring/sending-traces-with-opentelemetry/"
},
@@ -5636,7 +5492,7 @@
"svelte",
"sveltekit",
"nextjs",
"next.js"
"next.js"
],
"link": "/docs/frontend-monitoring/sending-metrics-with-opentelemetry/"
},
@@ -5683,7 +5539,6 @@
"label": "Golang Metrics",
"imgUrl": "/Logos/go.svg",
"tags": [
"apm/traces",
"metrics"
],
"module": "metrics",
@@ -5737,12 +5592,64 @@
]
}
},
{
"dataSource": "java-metrics",
"label": "Java Metrics",
"imgUrl": "/Logos/java.svg",
"tags": [
"metrics"
],
"module": "metrics",
"relatedSearchKeywords": [
"java",
"java metrics",
"java monitoring",
"java observability",
"jvm metrics",
"metrics",
"opentelemetry java",
"otel java",
"runtime metrics"
],
"id": "java-metrics",
"link": "/docs/metrics-management/send-metrics/applications/opentelemetry-java/",
"question": {
"desc": "What is your Environment?",
"type": "select",
"entityID": "environment",
"options": [
{
"key": "vm",
"label": "VM",
"imgUrl": "/Logos/vm.svg",
"link": "/docs/metrics-management/send-metrics/applications/opentelemetry-java/"
},
{
"key": "k8s",
"label": "Kubernetes",
"imgUrl": "/Logos/kubernetes.svg",
"link": "/docs/metrics-management/send-metrics/applications/opentelemetry-java/"
},
{
"key": "windows",
"label": "Windows",
"imgUrl": "/Logos/windows.svg",
"link": "/docs/metrics-management/send-metrics/applications/opentelemetry-java/"
},
{
"key": "docker",
"label": "Docker",
"imgUrl": "/Logos/docker.svg",
"link": "/docs/metrics-management/send-metrics/applications/opentelemetry-java/"
}
]
}
},
{
"dataSource": "python-metrics",
"label": "Python Metrics",
"imgUrl": "/Logos/python.svg",
"tags": [
"apm/traces",
"metrics"
],
"module": "metrics",
@@ -5796,7 +5703,6 @@
"label": ".NET Metrics",
"imgUrl": "/Logos/dotnet.svg",
"tags": [
"apm/traces",
"metrics"
],
"module": "metrics",
@@ -5853,7 +5759,6 @@
"label": "Node.js Metrics",
"imgUrl": "/Logos/nodejs.svg",
"tags": [
"apm/traces",
"metrics"
],
"module": "metrics",

View File

@@ -0,0 +1,31 @@
import { useMemo } from 'react';
import { TimeSeriesTooltipProps, TooltipContentItem } from '../types';
import Tooltip from './Tooltip';
import { buildTooltipContent } from './utils';
export default function TimeSeriesTooltip(
props: TimeSeriesTooltipProps,
): JSX.Element {
const content = useMemo(
(): TooltipContentItem[] =>
buildTooltipContent({
data: props.uPlotInstance.data,
series: props.uPlotInstance.series,
dataIndexes: props.dataIndexes,
activeSeriesIndex: props.seriesIndex,
uPlotInstance: props.uPlotInstance,
yAxisUnit: props.yAxisUnit ?? '',
decimalPrecision: props.decimalPrecision,
}),
[
props.uPlotInstance,
props.seriesIndex,
props.dataIndexes,
props.yAxisUnit,
props.decimalPrecision,
],
);
return <Tooltip {...props} content={content} />;
}

View File

@@ -5,8 +5,7 @@ import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
import dayjs from 'dayjs';
import { useIsDarkMode } from 'hooks/useDarkMode';
import { TooltipContentItem, TooltipProps } from '../types';
import { buildTooltipContent } from './utils';
import { TooltipProps } from '../types';
import './Tooltip.styles.scss';
@@ -14,14 +13,12 @@ const TOOLTIP_LIST_MAX_HEIGHT = 330;
const TOOLTIP_ITEM_HEIGHT = 38;
export default function Tooltip({
seriesIndex,
dataIndexes,
uPlotInstance,
timezone,
yAxisUnit = '',
decimalPrecision,
content,
}: TooltipProps): JSX.Element {
const isDarkMode = useIsDarkMode();
const headerTitle = useMemo(() => {
const data = uPlotInstance.data;
const cursorIdx = uPlotInstance.cursor.idx;
@@ -33,20 +30,6 @@ export default function Tooltip({
.format(DATE_TIME_FORMATS.MONTH_DATETIME_SECONDS);
}, [timezone, uPlotInstance.data, uPlotInstance.cursor.idx]);
const content = useMemo(
(): TooltipContentItem[] =>
buildTooltipContent({
data: uPlotInstance.data,
series: uPlotInstance.series,
dataIndexes,
activeSeriesIndex: seriesIndex,
uPlotInstance,
yAxisUnit,
decimalPrecision,
}),
[uPlotInstance, seriesIndex, dataIndexes, yAxisUnit, decimalPrecision],
);
return (
<div
className={cx(

View File

@@ -20,6 +20,27 @@ export function resolveSeriesColor(
return FALLBACK_SERIES_COLOR;
}
export function getTooltipBaseValue({
data,
index,
dataIndex,
isStackedBarChart,
}: {
data: AlignedData;
index: number;
dataIndex: number;
isStackedBarChart?: boolean;
}): number | null {
let baseValue = data[index][dataIndex] ?? null;
if (isStackedBarChart && index + 1 < data.length && baseValue !== null) {
const nextValue = data[index + 1][dataIndex] ?? null;
if (nextValue !== null) {
baseValue = baseValue - nextValue;
}
}
return baseValue;
}
export function buildTooltipContent({
data,
series,
@@ -28,6 +49,7 @@ export function buildTooltipContent({
uPlotInstance,
yAxisUnit,
decimalPrecision,
isStackedBarChart,
}: {
data: AlignedData;
series: Series[];
@@ -36,6 +58,7 @@ export function buildTooltipContent({
uPlotInstance: uPlot;
yAxisUnit: string;
decimalPrecision?: PrecisionOption;
isStackedBarChart?: boolean;
}): TooltipContentItem[] {
const active: TooltipContentItem[] = [];
const rest: TooltipContentItem[] = [];
@@ -52,23 +75,29 @@ export function buildTooltipContent({
continue;
}
const raw = data[index]?.[dataIndex];
const value = Number(raw);
const displayValue = Number.isNaN(value) ? 0 : value;
const baseValue = getTooltipBaseValue({
data,
index,
dataIndex,
isStackedBarChart,
});
const isActive = index === activeSeriesIndex;
const item: TooltipContentItem = {
label: String(s.label ?? ''),
value: displayValue,
tooltipValue: getToolTipValue(displayValue, yAxisUnit, decimalPrecision),
color: resolveSeriesColor(s.stroke, uPlotInstance, index),
isActive,
};
if (Number.isFinite(baseValue) && baseValue !== null) {
const item: TooltipContentItem = {
label: String(s.label ?? ''),
value: baseValue,
tooltipValue: getToolTipValue(baseValue, yAxisUnit, decimalPrecision),
color: resolveSeriesColor(s.stroke, uPlotInstance, index),
isActive,
};
if (isActive) {
active.push(item);
} else {
rest.push(item);
if (isActive) {
active.push(item);
} else {
rest.push(item);
}
}
}

View File

@@ -59,10 +59,22 @@ export interface TooltipRenderArgs {
viaSync: boolean;
}
export type TooltipProps = TooltipRenderArgs & {
export interface BaseTooltipProps {
timezone: string;
yAxisUnit?: string;
decimalPrecision?: PrecisionOption;
}
export interface TimeSeriesTooltipProps
extends BaseTooltipProps,
TooltipRenderArgs {}
export interface BarTooltipProps extends BaseTooltipProps, TooltipRenderArgs {
isStackedBarChart?: boolean;
}
export type TooltipProps = (TimeSeriesTooltipProps | BarTooltipProps) & {
content: TooltipContentItem[];
};
export enum LegendPosition {

View File

@@ -110,6 +110,7 @@ export enum LineStyle {
export enum DrawStyle {
Line = 'line',
Points = 'points',
Bar = 'bar',
}
export enum LineInterpolation {
@@ -128,7 +129,7 @@ export enum VisibilityMode {
export interface SeriesProps {
scaleKey: string;
label?: string;
panelType: PANEL_TYPES;
colorMapping: Record<string, string>;
drawStyle: DrawStyle;
pathBuilder?: Series.PathBuilder;

View File

@@ -247,8 +247,6 @@ func FilterResponse(results []*qbtypes.QueryRangeResponse) []*qbtypes.QueryRange
}
}
resultData.Rows = filteredRows
case *qbtypes.ScalarData:
resultData.Data = filterScalarDataIPs(resultData.Columns, resultData.Data)
}
filteredData = append(filteredData, result)
@@ -274,39 +272,6 @@ func shouldIncludeSeries(series *qbtypes.TimeSeries) bool {
return true
}
func filterScalarDataIPs(columns []*qbtypes.ColumnDescriptor, data [][]any) [][]any {
// Find column indices for server address fields
serverColIndices := make([]int, 0)
for i, col := range columns {
if col.Name == serverAddressKeyLegacy || col.Name == serverAddressKey {
serverColIndices = append(serverColIndices, i)
}
}
if len(serverColIndices) == 0 {
return data
}
filtered := make([][]any, 0, len(data))
for _, row := range data {
includeRow := true
for _, colIdx := range serverColIndices {
if colIdx < len(row) {
if strVal, ok := row[colIdx].(string); ok {
if net.ParseIP(strVal) != nil {
includeRow = false
break
}
}
}
}
if includeRow {
filtered = append(filtered, row)
}
}
return filtered
}
func shouldIncludeRow(row *qbtypes.RawRow) bool {
if row.Data != nil {
for _, key := range []string{serverAddressKeyLegacy, serverAddressKey} {

View File

@@ -116,59 +116,6 @@ func TestFilterResponse(t *testing.T) {
},
},
},
{
name: "should filter out IP addresses from scalar data",
input: []*qbtypes.QueryRangeResponse{
{
Data: qbtypes.QueryData{
Results: []any{
&qbtypes.ScalarData{
QueryName: "endpoints",
Columns: []*qbtypes.ColumnDescriptor{
{
TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{Name: "net.peer.name"},
Type: qbtypes.ColumnTypeGroup,
},
{
TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{Name: "endpoints"},
Type: qbtypes.ColumnTypeAggregation,
},
},
Data: [][]any{
{"192.168.1.1", 10},
{"example.com", 20},
{"10.0.0.1", 5},
},
},
},
},
},
},
expected: []*qbtypes.QueryRangeResponse{
{
Data: qbtypes.QueryData{
Results: []any{
&qbtypes.ScalarData{
QueryName: "endpoints",
Columns: []*qbtypes.ColumnDescriptor{
{
TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{Name: "net.peer.name"},
Type: qbtypes.ColumnTypeGroup,
},
{
TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{Name: "endpoints"},
Type: qbtypes.ColumnTypeAggregation,
},
},
Data: [][]any{
{"example.com", 20},
},
},
},
},
},
},
},
}
for _, tt := range tests {

View File

@@ -830,7 +830,7 @@ func (r *ClickHouseReader) GetUsage(ctx context.Context, queryParams *model.GetU
func (r *ClickHouseReader) GetSpansForTrace(ctx context.Context, traceID string, traceDetailsQuery string) ([]model.SpanItemV2, *model.ApiError) {
var traceSummary model.TraceSummary
summaryQuery := fmt.Sprintf("SELECT * from %s.%s FINAL WHERE trace_id=$1", r.TraceDB, r.traceSummaryTable)
summaryQuery := fmt.Sprintf("SELECT trace_id, min(start) AS start, max(end) AS end, sum(num_spans) AS num_spans FROM %s.%s WHERE trace_id=$1 GROUP BY trace_id", r.TraceDB, r.traceSummaryTable)
err := r.db.QueryRow(ctx, summaryQuery, traceID).Scan(&traceSummary.TraceID, &traceSummary.Start, &traceSummary.End, &traceSummary.NumSpans)
if err != nil {
if err == sql.ErrNoRows {
@@ -6458,7 +6458,7 @@ func (r *ClickHouseReader) SearchTraces(ctx context.Context, params *model.Searc
}
var traceSummary model.TraceSummary
summaryQuery := fmt.Sprintf("SELECT * from %s.%s FINAL WHERE trace_id=$1", r.TraceDB, r.traceSummaryTable)
summaryQuery := fmt.Sprintf("SELECT trace_id, min(start) AS start, max(end) AS end, sum(num_spans) AS num_spans FROM %s.%s WHERE trace_id=$1 GROUP BY trace_id", r.TraceDB, r.traceSummaryTable)
err := r.db.QueryRow(ctx, summaryQuery, params.TraceID).Scan(&traceSummary.TraceID, &traceSummary.Start, &traceSummary.End, &traceSummary.NumSpans)
if err != nil {
if err == sql.ErrNoRows {