Compare commits

..

21 Commits

Author SHA1 Message Date
Srikanth Chekuri
18e856f62c Merge branch 'main' into perf/panel-rerender 2025-12-16 09:44:30 +05:30
Abhi kumar
c0bd545e26 Merge branch 'main' into perf/panel-rerender 2025-12-02 16:47:40 +05:30
Abhi kumar
346be7b7ba Merge branch 'main' into perf/panel-rerender 2025-11-19 11:19:01 +05:30
Abhi kumar
10176e3128 Merge branch 'main' into perf/panel-rerender 2025-11-19 09:57:07 +05:30
Abhi kumar
a6832d6ed0 Merge branch 'main' into perf/panel-rerender 2025-11-18 16:17:58 +05:30
Abhi kumar
5504e90620 Merge branch 'main' into perf/panel-rerender 2025-11-17 10:43:08 +05:30
Srikanth Chekuri
19cffa0165 Merge branch 'main' into perf/panel-rerender 2025-11-13 23:21:05 +05:30
Abhi kumar
4dc4a0b95e Merge branch 'main' into perf/panel-rerender 2025-11-13 11:44:04 +05:30
Srikanth Chekuri
2462f551be Merge branch 'main' into perf/panel-rerender 2025-11-11 13:15:30 +05:30
Abhi Kumar
78ab80d294 fix: removed unnessasary usememo 2025-11-06 17:59:34 +05:30
Abhi Kumar
d285b90f09 Merge branch 'main' of https://github.com/SigNoz/signoz into perf/panel-rerender 2025-11-06 17:53:45 +05:30
Abhi kumar
08e756cf5d Merge branch 'main' into perf/panel-rerender 2025-11-06 17:08:48 +05:30
Abhi Kumar
42c1ddda39 chore: removing deepcompare for all the props 2025-11-06 15:45:27 +05:30
Abhi Kumar
efb85fc205 Merge branch 'main' of https://github.com/SigNoz/signoz into perf/panel-rerender 2025-11-06 14:57:34 +05:30
Abhi Kumar
0e972257db perf: memoize click handlers and use refs for dashboard mutations 2025-11-06 11:36:01 +05:30
Abhi Kumar
f8144e3a1d perf: added deep comparision for props 2025-11-06 11:31:11 +05:30
Abhi Kumar
02a8a11976 chore: removed useMemo from clickhandler 2025-11-06 11:29:10 +05:30
Abhi Kumar
4a351e5280 perf: added changes to make onclickhandler stable 2025-11-06 11:28:27 +05:30
Abhi Kumar
311257a518 perf: memoized panelwrapper and not rerendering it when onclickhandler is changing 2025-11-06 02:31:25 +05:30
Abhi Kumar
d5c665a72a perf: only calling getUplotchartdata when the props are changing 2025-11-06 02:27:31 +05:30
Abhi Kumar
0d6c8785d9 perf: memoized certain expensive functions 2025-11-06 02:26:51 +05:30
24 changed files with 361 additions and 430 deletions

View File

@@ -473,49 +473,6 @@ paths:
summary: Get reset password token
tags:
- users
/api/v1/ingestion:
get:
deprecated: false
description: This endpoints returns ingestion details
operationId: GetIngestion
responses:
"200":
content:
application/json:
schema:
properties:
data:
$ref: '#/components/schemas/IngestiontypesGettableIngestion'
status:
type: string
type: object
description: OK
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Forbidden
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Internal Server Error
security:
- api_key:
- EDITOR
- tokenizer:
- EDITOR
summary: Get ingestion details
tags:
- ingestion
/api/v1/invite:
get:
deprecated: false
@@ -2108,11 +2065,6 @@ components:
message:
type: string
type: object
IngestiontypesGettableIngestion:
properties:
url:
type: string
type: object
PreferencetypesPreference:
properties:
allowedScopes:

View File

@@ -132,34 +132,117 @@ function CeleryTaskBar({
[selectedFilters, celerySuccessStateData],
);
const onGraphClick = (
widgetData: Widgets,
xValue: number,
_yValue: number,
_mouseX: number,
_mouseY: number,
data?: {
[key: string]: string;
const onGraphClick = useCallback(
(
widgetData: Widgets,
xValue: number,
_yValue: number,
_mouseX: number,
_mouseY: number,
data?: {
[key: string]: string;
},
): void => {
const { start, end } = getStartAndEndTimesInMilliseconds(xValue);
// Extract entity and value from data
const [firstDataPoint] = Object.entries(data || {});
const [entity, value] = (firstDataPoint || ([] as unknown)) as [
string,
string,
];
if (!isEmpty(entity) || !isEmpty(value)) {
onClick?.({
entity,
value,
timeRange: [start, end],
widgetData,
});
}
},
): void => {
const { start, end } = getStartAndEndTimesInMilliseconds(xValue);
[onClick],
);
// Extract entity and value from data
const [firstDataPoint] = Object.entries(data || {});
const [entity, value] = (firstDataPoint || ([] as unknown)) as [
string,
string,
];
const onAllStateClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data?: any,
): void => {
onGraphClick(
celerySlowestTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
);
},
[onGraphClick],
);
if (!isEmpty(entity) || !isEmpty(value)) {
onClick?.({
entity,
value,
timeRange: [start, end],
widgetData,
});
}
};
const onFailedStateClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data?: any,
): void => {
onGraphClick(
celeryFailedTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
);
},
[onGraphClick],
);
const onRetryStateClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data?: any,
): void => {
onGraphClick(
celeryRetryTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
);
},
[onGraphClick],
);
const onSuccessStateClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data?: any,
): void => {
onGraphClick(
celerySuccessTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
);
},
[onGraphClick],
);
const { getCustomSeries } = useGetGraphCustomSeries({
isDarkMode,
@@ -185,16 +268,7 @@ function CeleryTaskBar({
headerMenuList={[...ViewMenuAction]}
onDragSelect={onDragSelect}
isQueryEnabled={queryEnabled}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void =>
onGraphClick(
celerySlowestTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
)
}
onClickHandler={onAllStateClick}
customSeries={getCustomSeries}
dataAvailable={checkIfDataExists}
/>
@@ -205,16 +279,7 @@ function CeleryTaskBar({
headerMenuList={[...ViewMenuAction]}
onDragSelect={onDragSelect}
isQueryEnabled={queryEnabled}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void =>
onGraphClick(
celeryFailedTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
)
}
onClickHandler={onFailedStateClick}
customSeries={getCustomSeries}
/>
)}
@@ -224,16 +289,7 @@ function CeleryTaskBar({
headerMenuList={[...ViewMenuAction]}
onDragSelect={onDragSelect}
isQueryEnabled={queryEnabled}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void =>
onGraphClick(
celeryRetryTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
)
}
onClickHandler={onRetryStateClick}
customSeries={getCustomSeries}
/>
)}
@@ -243,16 +299,7 @@ function CeleryTaskBar({
headerMenuList={[...ViewMenuAction]}
onDragSelect={onDragSelect}
isQueryEnabled={queryEnabled}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void =>
onGraphClick(
celerySuccessTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
)
}
onClickHandler={onSuccessStateClick}
customSeries={getCustomSeries}
/>
)}

View File

@@ -26,6 +26,7 @@ import {
SetStateAction,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
@@ -76,6 +77,7 @@ function WidgetGraphComponent({
const isFullViewOpen = params.get(QueryParams.expandedWidgetId) === widget.id;
const lineChartRef = useRef<ToggleGraphProps>();
const [graphVisibility, setGraphVisibility] = useState<boolean[]>(
Array(queryResponse.data?.payload?.data?.result?.length || 0).fill(true),
);
@@ -110,7 +112,7 @@ function WidgetGraphComponent({
const updateDashboardMutation = useUpdateDashboard();
const onDeleteHandler = (): void => {
const onDeleteHandler = useCallback((): void => {
if (!selectedDashboard) return;
const updatedWidgets = selectedDashboard?.data?.widgets?.filter(
@@ -138,9 +140,15 @@ function WidgetGraphComponent({
setDeleteModal(false);
},
});
};
}, [
selectedDashboard,
widget.id,
updateDashboardMutation,
setLayouts,
setSelectedDashboard,
]);
const onCloneHandler = async (): Promise<void> => {
const onCloneHandler = useCallback(async (): Promise<void> => {
if (!selectedDashboard) return;
const uuid = v4();
@@ -204,9 +212,18 @@ function WidgetGraphComponent({
},
},
);
};
}, [
selectedDashboard,
widget,
updateDashboardMutation,
setLayouts,
setSelectedDashboard,
notifications,
safeNavigate,
pathname,
]);
const handleOnView = (): void => {
const handleOnView = useCallback((): void => {
const queryParams = {
[QueryParams.expandedWidgetId]: widget.id,
};
@@ -225,17 +242,17 @@ function WidgetGraphComponent({
pathname,
search: newSearch,
});
};
}, [widget.id, search, pathname, safeNavigate]);
const handleOnDelete = (): void => {
const handleOnDelete = useCallback((): void => {
onToggleModal(setDeleteModal);
};
}, [onToggleModal]);
const onDeleteModelHandler = (): void => {
const onDeleteModelHandler = useCallback((): void => {
onToggleModal(setDeleteModal);
};
}, [onToggleModal]);
const onToggleModelHandler = (): void => {
const onToggleModelHandler = useCallback((): void => {
const existingSearchParams = new URLSearchParams(search);
existingSearchParams.delete(QueryParams.expandedWidgetId);
existingSearchParams.delete(QueryParams.compositeQuery);
@@ -254,63 +271,84 @@ function WidgetGraphComponent({
pathname,
search: createQueryParams(updatedQueryParams),
});
};
}, [search, queryResponse.data?.payload, widget.id, pathname, safeNavigate]);
const [searchTerm, setSearchTerm] = useState<string>('');
// Memoize the isButtonEnabled value to prevent recalculation
const isGraphClickButtonEnabled = useMemo(
() =>
(widget?.query?.builder?.queryData &&
Array.isArray(widget.query.builder.queryData)
? widget.query.builder.queryData
: []
).some(
(q) =>
q.dataSource === DataSource.TRACES || q.dataSource === DataSource.LOGS,
),
[widget?.query?.builder?.queryData],
);
const graphClick = useGraphClickToShowButton({
graphRef: currentGraphRef?.current ? currentGraphRef : graphRef,
isButtonEnabled: (widget?.query?.builder?.queryData &&
Array.isArray(widget.query.builder.queryData)
? widget.query.builder.queryData
: []
).some(
(q) =>
q.dataSource === DataSource.TRACES || q.dataSource === DataSource.LOGS,
),
isButtonEnabled: isGraphClickButtonEnabled,
buttonClassName: 'view-onclick-show-button',
});
const navigateToExplorer = useNavigateToExplorer();
const graphClickHandler = (
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
metric?: { [key: string]: string },
queryData?: { queryName: string; inFocusOrNot: boolean },
): void => {
const customTracesTimeRange = getCustomTimeRangeWindowSweepInMS(
const graphClickHandler = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
metric?: { [key: string]: string },
queryData?: { queryName: string; inFocusOrNot: boolean },
): void => {
const customTracesTimeRange = getCustomTimeRangeWindowSweepInMS(
customTimeRangeWindowForCoRelation,
);
const { start, end } = getStartAndEndTimesInMilliseconds(
xValue,
customTracesTimeRange,
);
handleGraphClick({
xValue,
yValue,
mouseX,
mouseY,
metric,
queryData,
widget,
navigateToExplorerPages,
navigateToExplorer,
notifications,
graphClick,
...(customTimeRangeWindowForCoRelation
? { customTracesTimeRange: { start, end } }
: {}),
});
},
[
customTimeRangeWindowForCoRelation,
);
const { start, end } = getStartAndEndTimesInMilliseconds(
xValue,
customTracesTimeRange,
);
handleGraphClick({
xValue,
yValue,
mouseX,
mouseY,
metric,
queryData,
widget,
navigateToExplorerPages,
navigateToExplorer,
notifications,
graphClick,
...(customTimeRangeWindowForCoRelation
? { customTracesTimeRange: { start, end } }
: {}),
});
};
],
);
const { truncatedText, fullText } = useGetResolvedText({
text: widget.title as string,
maxLength: 100,
});
// Use the provided onClickHandler if available, otherwise use the default graphClickHandler
// Both should be stable references due to useCallback
const clickHandler = onClickHandler ?? graphClickHandler;
return (
<div
style={{
@@ -366,7 +404,7 @@ function WidgetGraphComponent({
yAxisUnit={widget.yAxisUnit}
onToggleModelHandler={onToggleModelHandler}
tableProcessedDataRef={tableProcessedDataRef}
onClickHandler={onClickHandler ?? graphClickHandler}
onClickHandler={clickHandler}
customOnDragSelect={customOnDragSelect}
setCurrentGraphRef={setCurrentGraphRef}
enableDrillDown={
@@ -416,7 +454,7 @@ function WidgetGraphComponent({
setRequestData={setRequestData}
setGraphVisibility={setGraphVisibility}
graphVisibility={graphVisibility}
onClickHandler={onClickHandler ?? graphClickHandler}
onClickHandler={clickHandler}
onDragSelect={onDragSelect}
tableProcessedDataRef={tableProcessedDataRef}
customTooltipElement={customTooltipElement}

View File

@@ -5,7 +5,7 @@ import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi';
import { useDashboard } from 'providers/Dashboard/Dashboard';
import { useCallback, useMemo } from 'react';
import { useCallback, useMemo, useRef } from 'react';
import { useMutation } from 'react-query';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
@@ -46,6 +46,11 @@ function useUpdatedQuery(): UseUpdatedQueryResult {
[selectedDashboard],
);
// Use ref to access latest mutateAsync without recreating the callback
// queryRangeMutation object recreates on every render, but mutateAsync is stable
const mutateAsyncRef = useRef(queryRangeMutation.mutateAsync);
mutateAsyncRef.current = queryRangeMutation.mutateAsync;
const getUpdatedQuery = useCallback(
async ({
widgetConfig,
@@ -63,12 +68,12 @@ function useUpdatedQuery(): UseUpdatedQueryResult {
});
// Execute query and process results
const queryResult = await queryRangeMutation.mutateAsync(queryPayload);
const queryResult = await mutateAsyncRef.current(queryPayload);
// Map query data from API response
return mapQueryDataFromApi(queryResult.data.compositeQuery);
},
[dynamicVariables, globalSelectedInterval, queryRangeMutation],
[dynamicVariables, globalSelectedInterval],
);
return {

View File

@@ -238,6 +238,86 @@ function External(): JSX.Element {
setSelectedData,
);
const onErrorPercentageClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data: any,
): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_error_percentage',
data,
);
},
[onGraphClickHandler],
);
const onDurationClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data: any,
): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_duration',
data,
);
},
[onGraphClickHandler],
);
const onRPSByAddressClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data: any,
): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_rps_by_address',
data,
);
},
[onGraphClickHandler],
);
const onDurationByAddressClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data: any,
): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_duration_by_address',
data,
);
},
[onGraphClickHandler],
);
return (
<>
<Row gutter={24}>
@@ -266,16 +346,7 @@ function External(): JSX.Element {
<Graph
headerMenuList={MENU_ITEMS}
widget={externalCallErrorWidget}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_error_percentage',
data,
);
}}
onClickHandler={onErrorPercentageClick}
onDragSelect={onDragSelect}
version={ENTITY_VERSION_V4}
/>
@@ -309,16 +380,7 @@ function External(): JSX.Element {
<Graph
headerMenuList={MENU_ITEMS}
widget={externalCallDurationWidget}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_duration',
data,
);
}}
onClickHandler={onDurationClick}
onDragSelect={onDragSelect}
version={ENTITY_VERSION_V4}
/>
@@ -353,16 +415,7 @@ function External(): JSX.Element {
<Graph
widget={externalCallRPSWidget}
headerMenuList={MENU_ITEMS}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): Promise<void> =>
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_rps_by_address',
data,
)
}
onClickHandler={onRPSByAddressClick}
onDragSelect={onDragSelect}
version={ENTITY_VERSION_V4}
/>
@@ -396,16 +449,7 @@ function External(): JSX.Element {
<Graph
widget={externalCallDurationAddressWidget}
headerMenuList={MENU_ITEMS}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_duration_by_address',
data,
);
}}
onClickHandler={onDurationByAddressClick}
onDragSelect={onDragSelect}
version={ENTITY_VERSION_V4}
/>

View File

@@ -1,4 +1,5 @@
import { FC } from 'react';
import isEqual from 'lodash-es/isEqual';
import { FC, memo } from 'react';
import { PanelTypeVsPanelWrapper } from './constants';
import { PanelWrapperProps } from './panelWrapper.types';
@@ -55,4 +56,36 @@ function PanelWrapper({
);
}
export default PanelWrapper;
function arePropsEqual(
prevProps: PanelWrapperProps,
nextProps: PanelWrapperProps,
): boolean {
// Destructure to separate props that need deep comparison from the rest
const {
widget: prevWidget,
queryResponse: prevQueryResponse,
...prevRest
} = prevProps;
const {
widget: nextWidget,
queryResponse: nextQueryResponse,
...nextRest
} = nextProps;
// Shallow equality check for all other props (primitives, functions, refs, arrays)
const restKeys = Object.keys(prevRest) as Array<
keyof Omit<PanelWrapperProps, 'widget' | 'queryResponse'>
>;
if (restKeys.some((key) => prevRest[key] !== nextRest[key])) {
return false;
}
// Deep equality only for widget config and query response data payload
return (
isEqual(prevWidget, nextWidget) &&
isEqual(prevQueryResponse.data?.payload, nextQueryResponse.data?.payload)
);
}
export default memo(PanelWrapper, arePropsEqual);

View File

@@ -132,11 +132,21 @@ function UplotPanelWrapper({
[selectedGraph, widget?.panelTypes, widget?.stackedBarChart],
);
const chartData = getUPlotChartData(
queryResponse?.data?.payload,
widget.fillSpans,
stackedBarChart,
hiddenGraph,
// Memoize chartData to prevent unnecessary recalculations
const chartData = useMemo(
() =>
getUPlotChartData(
queryResponse?.data?.payload,
widget.fillSpans,
stackedBarChart,
hiddenGraph,
),
[
queryResponse?.data?.payload,
widget.fillSpans,
stackedBarChart,
hiddenGraph,
],
);
useEffect(() => {

View File

@@ -77,6 +77,20 @@ function MessagingQueuesGraph(): JSX.Element {
});
}
};
const onClickHandler = useCallback(
(
xValue: number,
_yValue: number,
_mouseX: number,
_mouseY: number,
data?: any,
): void => {
setSelectedTimelineQuery(urlQuery, xValue, location, history, data);
},
[urlQuery, location, history],
);
return (
<Card
isDarkMode={isDarkMode}
@@ -86,9 +100,7 @@ function MessagingQueuesGraph(): JSX.Element {
<GridCard
widget={widgetData}
headerMenuList={[...ViewMenuAction]}
onClickHandler={(xValue, _yValue, _mouseX, _mouseY, data): void => {
setSelectedTimelineQuery(urlQuery, xValue, location, history, data);
}}
onClickHandler={onClickHandler}
onDragSelect={onDragSelect}
customTooltipElement={messagingQueueCustomTooltipText()}
dataAvailable={checkIfDataExists}

View File

@@ -1,7 +1,6 @@
package apiserver
import (
"net/url"
"time"
"github.com/SigNoz/signoz/pkg/factory"
@@ -11,7 +10,6 @@ import (
type Config struct {
Timeout Timeout `mapstructure:"timeout"`
Logging Logging `mapstructure:"logging"`
Web Web `mapstructure:"web"`
}
type Timeout struct {
@@ -28,11 +26,6 @@ type Logging struct {
ExcludedRoutes []string `mapstructure:"excluded_routes"`
}
type Web struct {
// the url under which apiserver is externally reachable (for example, if apiserver is served via a reverse proxy).
ExternalURL *url.URL `mapstructure:"external_url"`
}
func NewConfigFactory() factory.ConfigFactory {
return factory.NewConfigFactory(factory.MustNewName("apiserver"), newConfig)
}
@@ -55,12 +48,6 @@ func newConfig() factory.Config {
"/",
},
},
Web: Web{
ExternalURL: &url.URL{
Scheme: "http",
Host: "localhost:8080",
},
},
}
}

View File

@@ -2,7 +2,6 @@ package apiserver
import (
"context"
"net/url"
"testing"
"time"
@@ -18,7 +17,6 @@ func TestNewWithEnvProvider(t *testing.T) {
t.Setenv("SIGNOZ_APISERVER_TIMEOUT_MAX", "700s")
t.Setenv("SIGNOZ_APISERVER_TIMEOUT_EXCLUDED__ROUTES", "/excluded1,/excluded2")
t.Setenv("SIGNOZ_APISERVER_LOGGING_EXCLUDED__ROUTES", "/api/v1/health1")
t.Setenv("SIGNOZ_APISERVER_WEB_EXTERNAL__URL", "https://test.com")
conf, err := config.New(
context.Background(),
@@ -53,12 +51,6 @@ func TestNewWithEnvProvider(t *testing.T) {
"/api/v1/health1",
},
},
Web: Web{
ExternalURL: &url.URL{
Scheme: "https",
Host: "test.com",
},
},
}
assert.Equal(t, expected, actual)

View File

@@ -1,31 +0,0 @@
package signozapiserver
import (
"net/http"
"github.com/SigNoz/signoz/pkg/http/handler"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/ingestiontypes"
"github.com/gorilla/mux"
)
func (provider *provider) addIngestionRoutes(router *mux.Router) error {
if err := router.Handle("/api/v1/ingestion", handler.New(provider.authZ.EditAccess(provider.ingestionHandler.Get), handler.OpenAPIDef{
ID: "GetIngestion",
Tags: []string{"ingestion"},
Summary: "Get ingestion details",
Description: "This endpoints returns ingestion details",
Request: nil,
RequestContentType: "",
Response: new(ingestiontypes.GettableIngestion),
ResponseContentType: "application/json",
SuccessStatusCode: http.StatusOK,
ErrorStatusCodes: []int{},
Deprecated: false,
SecuritySchemes: newSecuritySchemes(types.RoleEditor),
})).Methods(http.MethodGet).GetError(); err != nil {
return err
}
return nil
}

View File

@@ -8,7 +8,6 @@ import (
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/http/handler"
"github.com/SigNoz/signoz/pkg/http/middleware"
"github.com/SigNoz/signoz/pkg/ingestion"
"github.com/SigNoz/signoz/pkg/modules/authdomain"
"github.com/SigNoz/signoz/pkg/modules/organization"
"github.com/SigNoz/signoz/pkg/modules/preference"
@@ -29,7 +28,6 @@ type provider struct {
sessionHandler session.Handler
authDomainHandler authdomain.Handler
preferenceHandler preference.Handler
ingestionHandler ingestion.Handler
}
func NewFactory(
@@ -40,10 +38,9 @@ func NewFactory(
sessionHandler session.Handler,
authDomainHandler authdomain.Handler,
preferenceHandler preference.Handler,
ingestionHandler ingestion.Handler,
) factory.ProviderFactory[apiserver.APIServer, apiserver.Config] {
return factory.NewProviderFactory(factory.MustNewName("signoz"), func(ctx context.Context, providerSettings factory.ProviderSettings, config apiserver.Config) (apiserver.APIServer, error) {
return newProvider(ctx, providerSettings, config, orgGetter, authz, orgHandler, userHandler, sessionHandler, authDomainHandler, preferenceHandler, ingestionHandler)
return newProvider(ctx, providerSettings, config, orgGetter, authz, orgHandler, userHandler, sessionHandler, authDomainHandler, preferenceHandler)
})
}
@@ -58,7 +55,6 @@ func newProvider(
sessionHandler session.Handler,
authDomainHandler authdomain.Handler,
preferenceHandler preference.Handler,
ingestionHandler ingestion.Handler,
) (apiserver.APIServer, error) {
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/apiserver/signozapiserver")
router := mux.NewRouter().UseEncodedPath()
@@ -72,7 +68,6 @@ func newProvider(
sessionHandler: sessionHandler,
authDomainHandler: authDomainHandler,
preferenceHandler: preferenceHandler,
ingestionHandler: ingestionHandler,
}
provider.authZ = middleware.NewAuthZ(settings.Logger(), orgGetter, authz)
@@ -109,10 +104,6 @@ func (provider *provider) AddToRouter(router *mux.Router) error {
return err
}
if err := provider.addIngestionRoutes(router); err != nil {
return err
}
return nil
}

View File

@@ -1,39 +0,0 @@
package ingestion
import (
"net/url"
"github.com/SigNoz/signoz/pkg/errors"
"github.com/SigNoz/signoz/pkg/factory"
)
var (
ErrCodeInvalidIngestionConfig = errors.MustNewCode("invalid_ingestion_config")
)
type Config struct {
URL *url.URL `mapstructure:"url"`
}
func NewConfigFactory() factory.ConfigFactory {
return factory.NewConfigFactory(factory.MustNewName("ingestion"), newConfig)
}
func newConfig() factory.Config {
return &Config{
URL: &url.URL{
Scheme: "http",
Host: "localhost:8080",
Path: "/",
},
}
}
func (c Config) Validate() error {
if c.URL == nil {
return errors.New(errors.TypeInvalidInput, ErrCodeInvalidIngestionConfig, "url is required")
}
return nil
}

View File

@@ -1,13 +0,0 @@
package ingestion
import (
"net/http"
)
type Ingestion interface {
GetConfig() Config
}
type Handler interface {
Get(http.ResponseWriter, *http.Request)
}

View File

@@ -1,23 +0,0 @@
package signozingestion
import (
"net/http"
"github.com/SigNoz/signoz/pkg/http/render"
"github.com/SigNoz/signoz/pkg/ingestion"
"github.com/SigNoz/signoz/pkg/types/ingestiontypes"
)
type signozapi struct {
ingestion ingestion.Ingestion
}
func NewHandler(ingestion ingestion.Ingestion) ingestion.Handler {
return &signozapi{ingestion: ingestion}
}
func (api *signozapi) Get(rw http.ResponseWriter, r *http.Request) {
cfg := api.ingestion.GetConfig()
render.Success(rw, http.StatusOK, ingestiontypes.NewGettableIngestion(cfg.URL))
}

View File

@@ -1,31 +0,0 @@
package signozingestion
import (
"context"
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/ingestion"
)
type provider struct {
config ingestion.Config
settings factory.ScopedProviderSettings
}
func NewFactory() factory.ProviderFactory[ingestion.Ingestion, ingestion.Config] {
return factory.NewProviderFactory(factory.MustNewName("signoz"), func(ctx context.Context, providerSettings factory.ProviderSettings, config ingestion.Config) (ingestion.Ingestion, error) {
return newProvider(ctx, providerSettings, config)
})
}
func newProvider(_ context.Context, providerSettings factory.ProviderSettings, config ingestion.Config) (ingestion.Ingestion, error) {
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/ingestion/signozingestion")
return &provider{
config: config,
settings: settings,
}, nil
}
func (provider *provider) GetConfig() ingestion.Config {
return provider.config
}

View File

@@ -18,7 +18,6 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/gateway"
"github.com/SigNoz/signoz/pkg/ingestion"
"github.com/SigNoz/signoz/pkg/instrumentation"
"github.com/SigNoz/signoz/pkg/modules/metricsexplorer"
"github.com/SigNoz/signoz/pkg/prometheus"
@@ -102,9 +101,6 @@ type Config struct {
// MetricsExplorer config
MetricsExplorer metricsexplorer.Config `mapstructure:"metricsexplorer"`
// Ingestion config
Ingestion ingestion.Config `mapstructure:"ingestion"`
}
// DeprecatedFlags are the flags that are deprecated and scheduled for removal.
@@ -165,7 +161,6 @@ func NewConfig(ctx context.Context, logger *slog.Logger, resolverConfig config.R
gateway.NewConfigFactory(),
tokenizer.NewConfigFactory(),
metricsexplorer.NewConfigFactory(),
ingestion.NewConfigFactory(),
}
conf, err := config.New(ctx, resolverConfig, configFactories)

View File

@@ -2,8 +2,6 @@ package signoz
import (
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/ingestion"
"github.com/SigNoz/signoz/pkg/ingestion/signozingestion"
"github.com/SigNoz/signoz/pkg/licensing"
"github.com/SigNoz/signoz/pkg/modules/apdex"
"github.com/SigNoz/signoz/pkg/modules/apdex/implapdex"
@@ -36,10 +34,9 @@ type Handlers struct {
SpanPercentile spanpercentile.Handler
Services services.Handler
MetricsExplorer metricsexplorer.Handler
Ingestion ingestion.Handler
}
func NewHandlers(modules Modules, providerSettings factory.ProviderSettings, querier querier.Querier, licensing licensing.Licensing, ingestion ingestion.Ingestion) Handlers {
func NewHandlers(modules Modules, providerSettings factory.ProviderSettings, querier querier.Querier, licensing licensing.Licensing) Handlers {
return Handlers{
SavedView: implsavedview.NewHandler(modules.SavedView),
Apdex: implapdex.NewHandler(modules.Apdex),
@@ -50,6 +47,5 @@ func NewHandlers(modules Modules, providerSettings factory.ProviderSettings, que
Services: implservices.NewHandler(modules.Services),
MetricsExplorer: implmetricsexplorer.NewHandler(modules.MetricsExplorer),
SpanPercentile: implspanpercentile.NewHandler(modules.SpanPercentile),
Ingestion: signozingestion.NewHandler(ingestion),
}
}

View File

@@ -38,7 +38,7 @@ func TestNewHandlers(t *testing.T) {
require.NoError(t, err)
modules := NewModules(sqlstore, tokenizer, emailing, providerSettings, orgGetter, alertmanager, nil, nil, nil, nil, nil, nil, nil, Config{})
handlers := NewHandlers(modules, providerSettings, nil, nil, nil)
handlers := NewHandlers(modules, providerSettings, nil, nil)
reflectVal := reflect.ValueOf(handlers)
for i := 0; i < reflectVal.NumField(); i++ {

View File

@@ -9,7 +9,6 @@ import (
"github.com/SigNoz/signoz/pkg/apiserver/signozapiserver"
"github.com/SigNoz/signoz/pkg/authz"
"github.com/SigNoz/signoz/pkg/http/handler"
"github.com/SigNoz/signoz/pkg/ingestion"
"github.com/SigNoz/signoz/pkg/instrumentation"
"github.com/SigNoz/signoz/pkg/modules/authdomain"
"github.com/SigNoz/signoz/pkg/modules/organization"
@@ -37,7 +36,6 @@ func NewOpenAPI(ctx context.Context, instrumentation instrumentation.Instrumenta
struct{ session.Handler }{},
struct{ authdomain.Handler }{},
struct{ preference.Handler }{},
struct{ ingestion.Handler }{},
).New(ctx, instrumentation.ToProviderSettings(), apiserver.Config{})
if err != nil {
return nil, err

View File

@@ -18,8 +18,6 @@ import (
"github.com/SigNoz/signoz/pkg/emailing/noopemailing"
"github.com/SigNoz/signoz/pkg/emailing/smtpemailing"
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/ingestion"
"github.com/SigNoz/signoz/pkg/ingestion/signozingestion"
"github.com/SigNoz/signoz/pkg/modules/authdomain/implauthdomain"
"github.com/SigNoz/signoz/pkg/modules/organization"
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
@@ -223,7 +221,7 @@ func NewQuerierProviderFactories(telemetryStore telemetrystore.TelemetryStore, p
)
}
func NewAPIServerProviderFactories(orgGetter organization.Getter, authz authz.AuthZ, ingestion ingestion.Ingestion, modules Modules, handlers Handlers) factory.NamedMap[factory.ProviderFactory[apiserver.APIServer, apiserver.Config]] {
func NewAPIServerProviderFactories(orgGetter organization.Getter, authz authz.AuthZ, modules Modules, handlers Handlers) factory.NamedMap[factory.ProviderFactory[apiserver.APIServer, apiserver.Config]] {
return factory.MustNewNamedMap(
signozapiserver.NewFactory(
orgGetter,
@@ -233,7 +231,6 @@ func NewAPIServerProviderFactories(orgGetter organization.Getter, authz authz.Au
implsession.NewHandler(modules.Session),
implauthdomain.NewHandler(modules.AuthDomain),
implpreference.NewHandler(modules.Preference),
signozingestion.NewHandler(ingestion),
),
)
}
@@ -245,9 +242,3 @@ func NewTokenizerProviderFactories(cache cache.Cache, sqlstore sqlstore.SQLStore
jwttokenizer.NewFactory(cache, tokenStore),
)
}
func NewIngestionProviderFactories() factory.NamedMap[factory.ProviderFactory[ingestion.Ingestion, ingestion.Config]] {
return factory.MustNewNamedMap(
signozingestion.NewFactory(),
)
}

View File

@@ -83,7 +83,6 @@ func TestNewProviderFactories(t *testing.T) {
NewAPIServerProviderFactories(
implorganization.NewGetter(implorganization.NewStore(sqlstoretest.New(sqlstore.Config{Provider: "sqlite"}, sqlmock.QueryMatcherEqual)), nil),
nil,
nil,
Modules{},
Handlers{},
)

View File

@@ -345,29 +345,18 @@ func New(
telemetrymetadata.AttributesMetadataLocalTableName,
)
ingestion, err := factory.NewProviderFromNamedMap(
ctx,
providerSettings,
config.Ingestion,
NewIngestionProviderFactories(),
"signoz",
)
if err != nil {
return nil, err
}
// Initialize all modules
modules := NewModules(sqlstore, tokenizer, emailing, providerSettings, orgGetter, alertmanager, analytics, querier, telemetrystore, telemetryMetadataStore, authNs, authz, cache, config)
// Initialize all handlers for the modules
handlers := NewHandlers(modules, providerSettings, querier, licensing, ingestion)
handlers := NewHandlers(modules, providerSettings, querier, licensing)
// Initialize the API server
apiserver, err := factory.NewProviderFromNamedMap(
ctx,
providerSettings,
config.APIServer,
NewAPIServerProviderFactories(orgGetter, authz, ingestion, modules, handlers),
NewAPIServerProviderFactories(orgGetter, authz, modules, handlers),
"signoz",
)
if err != nil {

View File

@@ -1,11 +0,0 @@
package ingestiontypes
import "net/url"
type GettableIngestion struct {
URL string `json:"url"`
}
func NewGettableIngestion(url *url.URL) *GettableIngestion {
return &GettableIngestion{URL: url.String()}
}