Compare commits

..

1 Commits

Author SHA1 Message Date
Shivanshu Raj Shrivastava
99cbd023b5 feat: adds server and handler changes
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
2025-05-13 16:20:02 +05:30
32 changed files with 106 additions and 535 deletions

View File

@@ -322,6 +322,7 @@ func (s *Server) createPublicServer(apiHandler *api.APIHandler, web web.Web) (*h
apiHandler.RegisterMessagingQueuesRoutes(r, am)
apiHandler.RegisterThirdPartyApiRoutes(r, am)
apiHandler.MetricExplorerRoutes(r, am)
apiHandler.RegisterTraceFunnelsRoutes(r, am)
c := cors.New(cors.Options{
AllowedOrigins: []string{"*"},

View File

@@ -5,7 +5,6 @@ import (
"database/sql"
"encoding/json"
"fmt"
"github.com/SigNoz/signoz/ee/query-service/constants"
"time"
"github.com/jmoiron/sqlx"
@@ -208,14 +207,6 @@ func (r *Repo) GetAllFeatures() ([]basemodel.Feature, error) {
return feature, err
}
env := constants.GetOrDefaultEnv("DOT_METRICS_MIGRATED", "false")
if env == "true" {
feature = append(feature, basemodel.Feature{
Name: "DOT_METRICS_ENABLED",
Active: true,
})
}
return feature, nil
}

View File

@@ -5,7 +5,6 @@ import setLocalStorageApi from 'api/browser/localstorage/set';
import logEvent from 'api/common/logEvent';
import NotFound from 'components/NotFound';
import Spinner from 'components/Spinner';
import UserpilotRouteTracker from 'components/UserpilotRouteTracker/UserpilotRouteTracker';
import { FeatureKeys } from 'constants/features';
import { LOCALSTORAGE } from 'constants/localStorage';
import ROUTES from 'constants/routes';
@@ -355,7 +354,6 @@ function App(): JSX.Element {
<ConfigProvider theme={themeConfig}>
<Router history={history}>
<CompatRouter>
<UserpilotRouteTracker />
<NotificationProvider>
<PrivateRoute>
<ResourceProvider>

View File

@@ -1,223 +0,0 @@
import { render } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { MemoryRouter } from 'react-router-dom';
import { Userpilot } from 'userpilot';
import UserpilotRouteTracker from './UserpilotRouteTracker';
// Mock constants
const INITIAL_PATH = '/initial';
const TIMER_DELAY = 100;
// Mock the userpilot module
jest.mock('userpilot', () => ({
Userpilot: {
reload: jest.fn(),
},
}));
// Mock location state
let mockLocation = {
pathname: INITIAL_PATH,
search: '',
hash: '',
state: null,
};
// Mock react-router-dom
jest.mock('react-router-dom', () => {
const originalModule = jest.requireActual('react-router-dom');
return {
...originalModule,
useLocation: jest.fn(() => mockLocation),
};
});
describe('UserpilotRouteTracker', () => {
beforeEach(() => {
jest.clearAllMocks();
// Reset timers
jest.useFakeTimers();
// Reset error mock implementation
(Userpilot.reload as jest.Mock).mockImplementation(() => {});
// Reset location to initial state
mockLocation = {
pathname: INITIAL_PATH,
search: '',
hash: '',
state: null,
};
});
afterEach(() => {
jest.useRealTimers();
});
it('calls Userpilot.reload on initial render', () => {
render(
<MemoryRouter>
<UserpilotRouteTracker />
</MemoryRouter>,
);
// Fast-forward timer to trigger the setTimeout in reloadUserpilot
act(() => {
jest.advanceTimersByTime(TIMER_DELAY);
});
expect(Userpilot.reload).toHaveBeenCalledTimes(1);
});
it('calls Userpilot.reload when pathname changes', () => {
const { rerender } = render(
<MemoryRouter>
<UserpilotRouteTracker />
</MemoryRouter>,
);
// Fast-forward initial render timer
act(() => {
jest.advanceTimersByTime(TIMER_DELAY);
});
jest.clearAllMocks();
// Create a new location object with different pathname
const newLocation = {
...mockLocation,
pathname: '/new-path',
};
// Update the mock location with new path and trigger re-render
act(() => {
mockLocation = newLocation;
// Force a component update with the new location
rerender(
<MemoryRouter>
<UserpilotRouteTracker />
</MemoryRouter>,
);
});
// Fast-forward timer to allow the setTimeout to execute
act(() => {
jest.advanceTimersByTime(TIMER_DELAY);
});
expect(Userpilot.reload).toHaveBeenCalledTimes(1);
});
it('calls Userpilot.reload when search parameters change', () => {
const { rerender } = render(
<MemoryRouter>
<UserpilotRouteTracker />
</MemoryRouter>,
);
// Fast-forward initial render timer
act(() => {
jest.advanceTimersByTime(TIMER_DELAY);
});
jest.clearAllMocks();
// Create a new location object with different search params
const newLocation = {
...mockLocation,
search: '?param=value',
};
// Update the mock location with new search and trigger re-render
// eslint-disable-next-line sonarjs/no-identical-functions
act(() => {
mockLocation = newLocation;
// Force a component update with the new location
rerender(
<MemoryRouter>
<UserpilotRouteTracker />
</MemoryRouter>,
);
});
// Fast-forward timer to allow the setTimeout to execute
act(() => {
jest.advanceTimersByTime(TIMER_DELAY);
});
expect(Userpilot.reload).toHaveBeenCalledTimes(1);
});
it('handles errors in Userpilot.reload gracefully', () => {
// Mock console.error to prevent test output noise and capture calls
const consoleErrorSpy = jest
.spyOn(console, 'error')
.mockImplementation(() => {});
// Instead of using the component, we test the error handling behavior directly
const errorMsg = 'Error message';
// Set up a function that has the same error handling behavior as in component
const testErrorHandler = (): void => {
try {
if (typeof Userpilot !== 'undefined' && Userpilot.reload) {
Userpilot.reload();
}
} catch (error) {
console.error('[Userpilot] Error reloading on route change:', error);
}
};
// Make Userpilot.reload throw an error
(Userpilot.reload as jest.Mock).mockImplementation(() => {
throw new Error(errorMsg);
});
// Execute the function that should handle errors
testErrorHandler();
// Verify error was logged
expect(consoleErrorSpy).toHaveBeenCalledWith(
'[Userpilot] Error reloading on route change:',
expect.any(Error),
);
// Restore console mock
consoleErrorSpy.mockRestore();
});
it('does not call Userpilot.reload when same route is rendered again', () => {
const { rerender } = render(
<MemoryRouter>
<UserpilotRouteTracker />
</MemoryRouter>,
);
// Fast-forward initial render timer
act(() => {
jest.advanceTimersByTime(TIMER_DELAY);
});
jest.clearAllMocks();
act(() => {
mockLocation = {
pathname: mockLocation.pathname,
search: mockLocation.search,
hash: mockLocation.hash,
state: mockLocation.state,
};
// Force a component update with the same location
rerender(
<MemoryRouter>
<UserpilotRouteTracker />
</MemoryRouter>,
);
});
// Fast-forward timer
act(() => {
jest.advanceTimersByTime(TIMER_DELAY);
});
// Should not call reload since path and search are the same
expect(Userpilot.reload).not.toHaveBeenCalled();
});
});

View File

@@ -1,60 +0,0 @@
import { useCallback, useEffect, useRef } from 'react';
import { useLocation } from 'react-router-dom';
import { Userpilot } from 'userpilot';
/**
* UserpilotRouteTracker - A component that tracks route changes and calls Userpilot.reload
* on actual page changes (pathname changes or significant query parameter changes).
*
* This component renders nothing and is designed to be placed once high in the component tree.
*/
function UserpilotRouteTracker(): null {
const location = useLocation();
const prevPathRef = useRef<string>(location.pathname);
const prevSearchRef = useRef<string>(location.search);
const isFirstRenderRef = useRef<boolean>(true);
// Function to reload Userpilot safely - using useCallback to avoid dependency issues
const reloadUserpilot = useCallback((): void => {
try {
if (typeof Userpilot !== 'undefined' && Userpilot.reload) {
setTimeout(() => {
Userpilot.reload();
}, 100);
}
} catch (error) {
console.error('[Userpilot] Error reloading on route change:', error);
}
}, []);
// Handle first render
useEffect(() => {
if (isFirstRenderRef.current) {
isFirstRenderRef.current = false;
reloadUserpilot();
}
}, [reloadUserpilot]);
// Handle route/query changes
useEffect(() => {
// Skip first render as it's handled by the effect above
if (isFirstRenderRef.current) {
return;
}
// Check if the path has changed or if significant query params have changed
const pathChanged = location.pathname !== prevPathRef.current;
const searchChanged = location.search !== prevSearchRef.current;
if (pathChanged || searchChanged) {
// Update refs
prevPathRef.current = location.pathname;
prevSearchRef.current = location.search;
reloadUserpilot();
}
}, [location.pathname, location.search, reloadUserpilot]);
return null;
}
export default UserpilotRouteTracker;

View File

@@ -1,3 +1,7 @@
export const ENVIRONMENT = {
baseURL: 'http://localhost:8080',
baseURL:
process?.env?.FRONTEND_API_ENDPOINT ||
process?.env?.GITPOD_WORKSPACE_URL?.replace('://', '://8080-') ||
'',
wsURL: process?.env?.WEBSOCKET_API_ENDPOINT || '',
};

View File

@@ -10,5 +10,4 @@ export enum FeatureKeys {
ONBOARDING_V3 = 'ONBOARDING_V3',
THIRD_PARTY_API = 'THIRD_PARTY_API',
TRACE_FUNNELS = 'TRACE_FUNNELS',
DOT_METRICS_ENABLED = 'DOT_METRICS_ENABLED',
}

View File

@@ -30,7 +30,6 @@ import { GlobalReducer } from 'types/reducer/globalTime';
import { Tags } from 'types/reducer/trace';
import { USER_ROLES } from 'types/roles';
import { FeatureKeys } from '../../../constants/features';
import { DOCS_LINKS } from '../constants';
import { columns, TIME_PICKER_OPTIONS } from './constants';
@@ -211,11 +210,6 @@ function ServiceMetrics({
const topLevelOperations = useMemo(() => Object.entries(data || {}), [data]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const queryRangeRequestData = useMemo(
() =>
getQueryRangeRequestData({
@@ -223,14 +217,12 @@ function ServiceMetrics({
minTime: timeRange.startTime * 1e6,
maxTime: timeRange.endTime * 1e6,
globalSelectedInterval,
dotMetricsEnabled,
}),
[
globalSelectedInterval,
timeRange.endTime,
timeRange.startTime,
topLevelOperations,
dotMetricsEnabled,
],
);

View File

@@ -21,7 +21,6 @@ export const databaseCallsRPS = ({
servicename,
legend,
tagFilterItems,
dotMetricsEnabled,
}: DatabaseCallsRPSProps): QueryBuilderData => {
const autocompleteData: BaseAutocompleteData[] = [
{
@@ -35,7 +34,7 @@ export const databaseCallsRPS = ({
{
dataType: DataTypes.String,
isColumn: false,
key: dotMetricsEnabled ? WidgetKeys.Db_system : WidgetKeys.Db_system_norm,
key: 'db_system',
type: 'tag',
},
];
@@ -44,9 +43,7 @@ export const databaseCallsRPS = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Resource,
@@ -78,7 +75,6 @@ export const databaseCallsRPS = ({
export const databaseCallsAvgDuration = ({
servicename,
tagFilterItems,
dotMetricsEnabled,
}: DatabaseCallProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = {
key: WidgetKeys.SignozDbLatencySum,
@@ -97,9 +93,7 @@ export const databaseCallsAvgDuration = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Resource,

View File

@@ -33,7 +33,6 @@ export const externalCallErrorPercent = ({
servicename,
legend,
tagFilterItems,
dotMetricsEnabled,
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = {
key: WidgetKeys.SignozExternalCallLatencyCount,
@@ -52,9 +51,7 @@ export const externalCallErrorPercent = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Resource,
@@ -65,7 +62,7 @@ export const externalCallErrorPercent = ({
{
id: '',
key: {
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
dataType: DataTypes.Int64,
isColumn: false,
type: MetricsType.Tag,
@@ -79,9 +76,7 @@ export const externalCallErrorPercent = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Resource,
@@ -126,7 +121,6 @@ export const externalCallErrorPercent = ({
export const externalCallDuration = ({
servicename,
tagFilterItems,
dotMetricsEnabled,
}: ExternalCallProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = {
dataType: DataTypes.Float64,
@@ -150,9 +144,7 @@ export const externalCallDuration = ({
key: {
dataType: DataTypes.String,
isColumn: false,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -192,7 +184,6 @@ export const externalCallRpsByAddress = ({
servicename,
legend,
tagFilterItems,
dotMetricsEnabled,
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
const autocompleteData: BaseAutocompleteData[] = [
{
@@ -209,9 +200,7 @@ export const externalCallRpsByAddress = ({
key: {
dataType: DataTypes.String,
isColumn: false,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -242,7 +231,6 @@ export const externalCallDurationByAddress = ({
servicename,
legend,
tagFilterItems,
dotMetricsEnabled,
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = {
dataType: DataTypes.Float64,
@@ -265,9 +253,7 @@ export const externalCallDurationByAddress = ({
key: {
dataType: DataTypes.String,
isColumn: false,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
type: MetricsType.Resource,
},
op: OPERATORS.IN,

View File

@@ -37,18 +37,10 @@ export const latency = ({
tagFilterItems,
isSpanMetricEnable = false,
topLevelOperationsRoute,
dotMetricsEnabled,
}: LatencyProps): QueryBuilderData => {
const signozLatencyBucketMetrics = dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm;
const signozMetricsServiceName = dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm;
const newAutoCompleteData: BaseAutocompleteData = {
key: isSpanMetricEnable
? signozLatencyBucketMetrics
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.DurationNano,
dataType: DataTypes.Float64,
isColumn: true,
@@ -61,7 +53,7 @@ export const latency = ({
{
id: '',
key: {
key: isSpanMetricEnable ? signozMetricsServiceName : WidgetKeys.ServiceName,
key: isSpanMetricEnable ? WidgetKeys.Service_name : WidgetKeys.ServiceName,
dataType: DataTypes.String,
type: isSpanMetricEnable ? MetricsType.Resource : MetricsType.Tag,
isColumn: !isSpanMetricEnable,
@@ -303,30 +295,23 @@ export const apDexMetricsQueryBuilderQueries = ({
threashold,
delta,
metricsBuckets,
dotMetricsEnabled,
}: ApDexMetricsQueryBuilderQueriesProps): QueryBuilderData => {
const autoCompleteDataA: BaseAutocompleteData = {
key: dotMetricsEnabled
? WidgetKeys.SignozLatencyCount
: WidgetKeys.SignozLatencyCountNorm,
key: WidgetKeys.SignozLatencyCount,
dataType: DataTypes.Float64,
isColumn: true,
type: '',
};
const autoCompleteDataB: BaseAutocompleteData = {
key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
key: WidgetKeys.Signoz_latency_bucket,
dataType: DataTypes.Float64,
isColumn: true,
type: '',
};
const autoCompleteDataC: BaseAutocompleteData = {
key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
key: WidgetKeys.Signoz_latency_bucket,
dataType: DataTypes.Float64,
isColumn: true,
type: '',
@@ -336,9 +321,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Tag,
@@ -364,7 +347,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Tag,
@@ -386,9 +369,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Tag,
@@ -425,7 +406,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Tag,
@@ -436,9 +417,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Tag,
@@ -503,13 +482,10 @@ export const operationPerSec = ({
servicename,
tagFilterItems,
topLevelOperations,
dotMetricsEnabled,
}: OperationPerSecProps): QueryBuilderData => {
const autocompleteData: BaseAutocompleteData[] = [
{
key: dotMetricsEnabled
? WidgetKeys.SignozLatencyCount
: WidgetKeys.SignozLatencyCountNorm,
key: WidgetKeys.SignozLatencyCount,
dataType: DataTypes.Float64,
isColumn: true,
type: '',
@@ -521,9 +497,7 @@ export const operationPerSec = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Resource,
@@ -566,7 +540,6 @@ export const errorPercentage = ({
servicename,
tagFilterItems,
topLevelOperations,
dotMetricsEnabled,
}: OperationPerSecProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = {
key: WidgetKeys.SignozCallsTotal,
@@ -587,9 +560,7 @@ export const errorPercentage = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Resource,
@@ -611,9 +582,7 @@ export const errorPercentage = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
dataType: DataTypes.Int64,
isColumn: false,
type: MetricsType.Tag,
@@ -628,9 +597,7 @@ export const errorPercentage = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Resource,

View File

@@ -21,12 +21,9 @@ import { getQueryBuilderQuerieswithFormula } from './MetricsPageQueriesFactory';
export const topOperationQueries = ({
servicename,
dotMetricsEnabled,
}: TopOperationQueryFactoryProps): QueryBuilderData => {
const latencyAutoCompleteData: BaseAutocompleteData = {
key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
key: WidgetKeys.Signoz_latency_bucket,
dataType: DataTypes.Float64,
isColumn: true,
type: '',
@@ -40,9 +37,7 @@ export const topOperationQueries = ({
};
const numOfCallAutoCompleteData: BaseAutocompleteData = {
key: dotMetricsEnabled
? WidgetKeys.SignozLatencyCount
: WidgetKeys.SignozLatencyCountNorm,
key: WidgetKeys.SignozLatencyCount,
dataType: DataTypes.Float64,
isColumn: true,
type: '',
@@ -52,9 +47,7 @@ export const topOperationQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
dataType: DataTypes.String,
isColumn: false,
type: MetricsType.Resource,
@@ -70,9 +63,7 @@ export const topOperationQueries = ({
key: {
dataType: DataTypes.String,
isColumn: false,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -83,7 +74,7 @@ export const topOperationQueries = ({
key: {
dataType: DataTypes.Int64,
isColumn: false,
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
type: MetricsType.Tag,
},
op: OPERATORS.IN,

View File

@@ -26,8 +26,6 @@ import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { GraphTitle, MENU_ITEMS, SERVICE_CHART_ID } from '../constant';
import { getWidgetQueryBuilder } from '../MetricsApplication.factory';
import { Card, GraphContainer, Row } from '../styles';
@@ -82,11 +80,8 @@ function DBCall(): JSX.Element {
[queries],
);
const legend = '{{db.system}}';
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const legend = '{{db_system}}';
const databaseCallsRPSWidget = useMemo(
() =>
getWidgetQueryBuilder({
@@ -97,7 +92,6 @@ function DBCall(): JSX.Element {
servicename,
legend,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -108,7 +102,7 @@ function DBCall(): JSX.Element {
id: SERVICE_CHART_ID.dbCallsRPS,
fillSpans: false,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const databaseCallsAverageDurationWidget = useMemo(
() =>
@@ -119,7 +113,6 @@ function DBCall(): JSX.Element {
builder: databaseCallsAvgDuration({
servicename,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -130,7 +123,7 @@ function DBCall(): JSX.Element {
id: GraphTitle.DATABASE_CALLS_AVG_DURATION,
fillSpans: true,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const stepInterval = useMemo(

View File

@@ -28,8 +28,6 @@ import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { GraphTitle, legend, MENU_ITEMS } from '../constant';
import { getWidgetQueryBuilder } from '../MetricsApplication.factory';
import { Card, GraphContainer, Row } from '../styles';
@@ -76,10 +74,6 @@ function External(): JSX.Element {
handleNonInQueryRange(resourceAttributesToTagFilterItems(queries)) || [],
[queries],
);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const externalCallErrorWidget = useMemo(
() =>
@@ -91,7 +85,6 @@ function External(): JSX.Element {
servicename,
legend: legend.address,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -101,7 +94,7 @@ function External(): JSX.Element {
yAxisUnit: '%',
id: GraphTitle.EXTERNAL_CALL_ERROR_PERCENTAGE,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const selectedTraceTags = useMemo(
@@ -118,7 +111,6 @@ function External(): JSX.Element {
builder: externalCallDuration({
servicename,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -129,7 +121,7 @@ function External(): JSX.Element {
id: GraphTitle.EXTERNAL_CALL_DURATION,
fillSpans: true,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const errorApmToTraceQuery = useGetAPMToTracesQueries({
@@ -188,7 +180,6 @@ function External(): JSX.Element {
servicename,
legend: legend.address,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -199,7 +190,7 @@ function External(): JSX.Element {
id: GraphTitle.EXTERNAL_CALL_RPS_BY_ADDRESS,
fillSpans: true,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const externalCallDurationAddressWidget = useMemo(
@@ -212,7 +203,6 @@ function External(): JSX.Element {
servicename,
legend: legend.address,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -223,7 +213,7 @@ function External(): JSX.Element {
id: GraphTitle.EXTERNAL_CALL_DURATION_BY_ADDRESS,
fillSpans: true,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const apmToTraceQuery = useGetAPMToTracesQueries({

View File

@@ -145,10 +145,6 @@ function Application(): JSX.Element {
[servicename, topLevelOperations],
);
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const operationPerSecWidget = useMemo(
() =>
getWidgetQueryBuilder({
@@ -159,7 +155,6 @@ function Application(): JSX.Element {
servicename,
tagFilterItems,
topLevelOperations: topLevelOperationsRoute,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -169,7 +164,7 @@ function Application(): JSX.Element {
yAxisUnit: 'ops',
id: SERVICE_CHART_ID.rps,
}),
[servicename, tagFilterItems, topLevelOperationsRoute, dotMetricsEnabled],
[servicename, tagFilterItems, topLevelOperationsRoute],
);
const errorPercentageWidget = useMemo(
@@ -182,7 +177,6 @@ function Application(): JSX.Element {
servicename,
tagFilterItems,
topLevelOperations: topLevelOperationsRoute,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -193,7 +187,7 @@ function Application(): JSX.Element {
id: SERVICE_CHART_ID.errorPercentage,
fillSpans: true,
}),
[servicename, tagFilterItems, topLevelOperationsRoute, dotMetricsEnabled],
[servicename, tagFilterItems, topLevelOperationsRoute],
);
const stepInterval = useMemo(

View File

@@ -20,8 +20,6 @@ import { useParams } from 'react-router-dom';
import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../../../constants/features';
import { useAppContext } from '../../../../../providers/App/App';
import { IServiceName } from '../../types';
import { ApDexMetricsProps } from './types';
@@ -36,10 +34,7 @@ function ApDexMetrics({
}: ApDexMetricsProps): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>();
const servicename = decodeURIComponent(encodedServiceName);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const apDexMetricsWidget = useMemo(
() =>
getWidgetQueryBuilder({
@@ -53,7 +48,6 @@ function ApDexMetrics({
threashold: thresholdValue || 0,
delta: delta || false,
metricsBuckets: metricsBuckets || [],
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -79,7 +73,6 @@ function ApDexMetrics({
tagFilterItems,
thresholdValue,
topLevelOperationsRoute,
dotMetricsEnabled,
],
);

View File

@@ -56,10 +56,6 @@ function ServiceOverview({
[isSpanMetricEnable, queries],
);
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.USE_SPAN_METRICS)
?.active || false;
const latencyWidget = useMemo(
() =>
getWidgetQueryBuilder({
@@ -71,7 +67,6 @@ function ServiceOverview({
tagFilterItems,
isSpanMetricEnable,
topLevelOperationsRoute,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -81,13 +76,7 @@ function ServiceOverview({
yAxisUnit: 'ns',
id: SERVICE_CHART_ID.latency,
}),
[
isSpanMetricEnable,
servicename,
tagFilterItems,
topLevelOperationsRoute,
dotMetricsEnabled,
],
[isSpanMetricEnable, servicename, tagFilterItems, topLevelOperationsRoute],
);
const isQueryEnabled =

View File

@@ -18,8 +18,6 @@ import { EQueryType } from 'types/common/dashboard';
import { GlobalReducer } from 'types/reducer/globalTime';
import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../../constants/features';
import { useAppContext } from '../../../../providers/App/App';
import { IServiceName } from '../types';
import { title } from './config';
import ColumnWithLink from './TableRenderer/ColumnWithLink';
@@ -42,11 +40,6 @@ function TopOperationMetrics(): JSX.Element {
convertRawQueriesToTraceSelectedTags(queries) || [],
);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const keyOperationWidget = useMemo(
() =>
getWidgetQueryBuilder({
@@ -55,14 +48,13 @@ function TopOperationMetrics(): JSX.Element {
promql: [],
builder: topOperationQueries({
servicename,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
},
panelTypes: PANEL_TYPES.TABLE,
}),
[servicename, dotMetricsEnabled],
[servicename],
);
const updatedQuery = useStepInterval(keyOperationWidget.query);

View File

@@ -10,7 +10,6 @@ export interface IServiceName {
export interface TopOperationQueryFactoryProps {
servicename: IServiceName['servicename'];
dotMetricsEnabled: boolean;
}
export interface ExternalCallDurationByAddressProps extends ExternalCallProps {
@@ -20,7 +19,6 @@ export interface ExternalCallDurationByAddressProps extends ExternalCallProps {
export interface ExternalCallProps {
servicename: IServiceName['servicename'];
tagFilterItems: TagFilterItem[];
dotMetricsEnabled: boolean;
}
export interface BuilderQueriesProps {
@@ -52,7 +50,6 @@ export interface OperationPerSecProps {
servicename: IServiceName['servicename'];
tagFilterItems: TagFilterItem[];
topLevelOperations: string[];
dotMetricsEnabled: boolean;
}
export interface LatencyProps {
@@ -60,7 +57,6 @@ export interface LatencyProps {
tagFilterItems: TagFilterItem[];
isSpanMetricEnable?: boolean;
topLevelOperationsRoute: string[];
dotMetricsEnabled: boolean;
}
export interface ApDexProps {
@@ -78,5 +74,4 @@ export interface TableRendererProps {
export interface ApDexMetricsQueryBuilderQueriesProps extends ApDexProps {
delta: boolean;
metricsBuckets: number[];
dotMetricsEnabled: boolean;
}

View File

@@ -85,15 +85,12 @@ export enum WidgetKeys {
HasError = 'hasError',
Address = 'address',
DurationNano = 'durationNano',
StatusCodeNorm = 'status_code',
StatusCode = 'status.code',
StatusCode = 'status_code',
Operation = 'operation',
OperationName = 'operationName',
Service_name_norm = 'service_name',
Service_name = 'service.name',
Service_name = 'service_name',
ServiceName = 'serviceName',
SignozLatencyCountNorm = 'signoz_latency_count',
SignozLatencyCount = 'signoz_latency.count',
SignozLatencyCount = 'signoz_latency_count',
SignozDBLatencyCount = 'signoz_db_latency_count',
DatabaseCallCount = 'signoz_database_call_count',
DatabaseCallLatencySum = 'signoz_database_call_latency_sum',
@@ -101,10 +98,7 @@ export enum WidgetKeys {
SignozCallsTotal = 'signoz_calls_total',
SignozExternalCallLatencyCount = 'signoz_external_call_latency_count',
SignozExternalCallLatencySum = 'signoz_external_call_latency_sum',
Signoz_latency_bucket_norm = 'signoz_latency_bucket',
Signoz_latency_bucket = 'signoz_latency.bucket',
Db_system = 'db.system',
Db_system_norm = 'db.system',
Signoz_latency_bucket = 'signoz_latency_bucket',
}
export const topOperationMetricsDownloadOptions: DownloadOptions = {

View File

@@ -25,11 +25,10 @@ export interface NavigateToTraceProps {
}
export interface DatabaseCallsRPSProps extends DatabaseCallProps {
legend: '{{db.system}}';
legend: '{{db_system}}';
}
export interface DatabaseCallProps {
servicename: IServiceName['servicename'];
tagFilterItems: TagFilterItem[];
dotMetricsEnabled: boolean;
}

View File

@@ -3,8 +3,6 @@ import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { ServiceMetricsProps } from '../types';
import { getQueryRangeRequestData } from '../utils';
import ServiceMetricTable from './ServiceMetricTable';
@@ -17,11 +15,6 @@ function ServiceMetricsApplication({
GlobalReducer
>((state) => state.globalTime);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const queryRangeRequestData = useMemo(
() =>
getQueryRangeRequestData({
@@ -29,15 +22,8 @@ function ServiceMetricsApplication({
minTime,
maxTime,
globalSelectedInterval,
dotMetricsEnabled,
}),
[
globalSelectedInterval,
maxTime,
minTime,
topLevelOperations,
dotMetricsEnabled,
],
[globalSelectedInterval, maxTime, minTime, topLevelOperations],
);
return (
<ServiceMetricTable

View File

@@ -19,14 +19,11 @@ import {
export const serviceMetricsQuery = (
topLevelOperation: [keyof ServiceDataProps, string[]],
dotMetricsEnabled: boolean,
): QueryBuilderData => {
const p99AutoCompleteData: BaseAutocompleteData = {
dataType: DataTypes.Float64,
isColumn: true,
key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
key: WidgetKeys.Signoz_latency_bucket,
type: '',
};
@@ -57,9 +54,7 @@ export const serviceMetricsQuery = (
key: {
dataType: DataTypes.String,
isColumn: false,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -84,9 +79,7 @@ export const serviceMetricsQuery = (
key: {
dataType: DataTypes.String,
isColumn: false,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -97,7 +90,7 @@ export const serviceMetricsQuery = (
key: {
dataType: DataTypes.Int64,
isColumn: false,
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
type: MetricsType.Tag,
},
op: OPERATORS.IN,
@@ -122,9 +115,7 @@ export const serviceMetricsQuery = (
key: {
dataType: DataTypes.String,
isColumn: false,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -149,9 +140,7 @@ export const serviceMetricsQuery = (
key: {
dataType: DataTypes.String,
isColumn: false,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -206,9 +195,7 @@ export const serviceMetricsQuery = (
{
dataType: DataTypes.String,
isColumn: false,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.Service_name,
type: MetricsType.Tag,
},
];

View File

@@ -29,7 +29,6 @@ export interface GetQueryRangeRequestDataProps {
maxTime: number;
minTime: number;
globalSelectedInterval: Time | TimeV2 | CustomTimeType;
dotMetricsEnabled: boolean;
}
export interface GetServiceListFromQueryProps {

View File

@@ -28,7 +28,6 @@ export const getQueryRangeRequestData = ({
maxTime,
minTime,
globalSelectedInterval,
dotMetricsEnabled,
}: GetQueryRangeRequestDataProps): GetQueryResultsProps[] => {
const requestData: GetQueryResultsProps[] = [];
topLevelOperations.forEach((operation) => {
@@ -36,7 +35,7 @@ export const getQueryRangeRequestData = ({
query: {
queryType: EQueryType.QUERY_BUILDER,
promql: [],
builder: serviceMetricsQuery(operation, dotMetricsEnabled),
builder: serviceMetricsQuery(operation),
clickhouse_sql: [],
id: uuid(),
},

View File

@@ -5663,3 +5663,33 @@ func (aH *APIHandler) getDomainInfo(w http.ResponseWriter, r *http.Request) {
}
aH.Respond(w, resp)
}
// RegisterTraceFunnelsRoutes adds trace funnels routes
func (aH *APIHandler) RegisterTraceFunnelsRoutes(router *mux.Router, am *middleware.AuthZ) {
// Main trace funnels router
traceFunnelsRouter := router.PathPrefix("/api/v1/trace-funnels").Subrouter()
// API endpoints
traceFunnelsRouter.HandleFunc("/new",
am.ViewAccess(aH.Signoz.Handlers.TraceFunnel.New)).
Methods(http.MethodPost)
traceFunnelsRouter.HandleFunc("/list",
am.ViewAccess(aH.Signoz.Handlers.TraceFunnel.List)).
Methods(http.MethodGet)
traceFunnelsRouter.HandleFunc("/steps/update",
am.ViewAccess(aH.Signoz.Handlers.TraceFunnel.UpdateSteps)).
Methods(http.MethodPut)
traceFunnelsRouter.HandleFunc("/{funnel_id}",
am.ViewAccess(aH.Signoz.Handlers.TraceFunnel.Get)).
Methods(http.MethodGet)
traceFunnelsRouter.HandleFunc("/{funnel_id}",
am.ViewAccess(aH.Signoz.Handlers.TraceFunnel.Delete)).
Methods(http.MethodDelete)
traceFunnelsRouter.HandleFunc("/{funnel_id}",
am.ViewAccess(aH.Signoz.Handlers.TraceFunnel.UpdateFunnel)).
Methods(http.MethodPut)
traceFunnelsRouter.HandleFunc("/save",
am.ViewAccess(aH.Signoz.Handlers.TraceFunnel.Save)).
Methods(http.MethodPost)
}

View File

@@ -263,11 +263,7 @@ func PrepareTimeseriesFilterQuery(start, end int64, mq *v3.BuilderQuery) (string
conditions = append(conditions, fmt.Sprintf("metric_name IN %s", utils.ClickHouseFormattedMetricNames(mq.AggregateAttribute.Key)))
conditions = append(conditions, fmt.Sprintf("temporality = '%s'", mq.Temporality))
if constants.GetOrDefaultEnv("DOT_METRICS_ENABLED", "true") == "true" {
conditions = append(conditions, "__normalized = false")
} else {
conditions = append(conditions, "__normalized = true")
}
conditions = append(conditions, "__normalized = true")
start, end, tableName := whichTSTableToUse(start, end, mq)
@@ -355,11 +351,7 @@ func PrepareTimeseriesFilterQueryV3(start, end int64, mq *v3.BuilderQuery) (stri
conditions = append(conditions, fmt.Sprintf("metric_name IN %s", utils.ClickHouseFormattedMetricNames(mq.AggregateAttribute.Key)))
conditions = append(conditions, fmt.Sprintf("temporality = '%s'", mq.Temporality))
if constants.GetOrDefaultEnv("DOT_METRICS_ENABLED", "true") == "true" {
conditions = append(conditions, "__normalized = false")
} else {
conditions = append(conditions, "__normalized = true")
}
conditions = append(conditions, "__normalized = true")
start, end, tableName := whichTSTableToUse(start, end, mq)

View File

@@ -149,8 +149,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
}
telemetry.GetInstance().SetReader(reader)
quickfiltermodule := quickfilterscore.NewQuickFilters(quickfilterscore.NewStore(serverOptions.SigNoz.SQLStore))
quickFilter := quickfilter.NewAPI(quickfiltermodule)
quickFilterModule := quickfilter.NewAPI(quickfilterscore.NewQuickFilters(quickfilterscore.NewStore(serverOptions.SigNoz.SQLStore)))
apiHandler, err := NewAPIHandler(APIHandlerOpts{
Reader: reader,
PreferSpanMetrics: serverOptions.PreferSpanMetrics,
@@ -165,8 +164,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
AlertmanagerAPI: alertmanager.NewAPI(serverOptions.SigNoz.Alertmanager),
FieldsAPI: fields.NewAPI(serverOptions.SigNoz.TelemetryStore),
Signoz: serverOptions.SigNoz,
QuickFilters: quickFilter,
QuickFilterModule: quickfiltermodule,
QuickFilters: quickFilterModule,
})
if err != nil {
return nil, err
@@ -283,6 +281,7 @@ func (s *Server) createPublicServer(api *APIHandler, web web.Web) (*http.Server,
api.RegisterMessagingQueuesRoutes(r, am)
api.RegisterThirdPartyApiRoutes(r, am)
api.MetricExplorerRoutes(r, am)
api.RegisterTraceFunnelsRoutes(r, am)
c := cors.New(cors.Options{
AllowedOrigins: []string{"*"},

View File

@@ -33,15 +33,6 @@ func (fm *FeatureManager) CheckFeature(featureKey string) error {
// GetFeatureFlags returns current features
func (fm *FeatureManager) GetFeatureFlags() (model.FeatureSet, error) {
features := constants.DEFAULT_FEATURE_SET
//dot metrics migration
env := constants.GetOrDefaultEnv("DOT_METRICS_ENABLED", "false")
if env == "true" {
features = append(features, model.Feature{
Name: "DOT_METRICS_MIGRATED",
Active: true,
})
}
return features, nil
}

View File

@@ -5,16 +5,20 @@ import (
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
"github.com/SigNoz/signoz/pkg/modules/preference"
"github.com/SigNoz/signoz/pkg/modules/preference/implpreference"
"github.com/SigNoz/signoz/pkg/modules/tracefunnel"
"github.com/SigNoz/signoz/pkg/modules/tracefunnel/impltracefunnel"
)
type Handlers struct {
Organization organization.Handler
Preference preference.Handler
TraceFunnel tracefunnel.Handler
}
func NewHandlers(modules Modules) Handlers {
return Handlers{
Organization: implorganization.NewHandler(modules.Organization),
Preference: implpreference.NewHandler(modules.Preference),
TraceFunnel: impltracefunnel.NewHandler(modules.TraceFunnel),
}
}

View File

@@ -5,6 +5,8 @@ import (
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
"github.com/SigNoz/signoz/pkg/modules/preference"
"github.com/SigNoz/signoz/pkg/modules/preference/implpreference"
"github.com/SigNoz/signoz/pkg/modules/tracefunnel"
"github.com/SigNoz/signoz/pkg/modules/tracefunnel/impltracefunnel"
"github.com/SigNoz/signoz/pkg/sqlstore"
"github.com/SigNoz/signoz/pkg/types/preferencetypes"
)
@@ -12,11 +14,13 @@ import (
type Modules struct {
Organization organization.Module
Preference preference.Module
TraceFunnel tracefunnel.Module
}
func NewModules(sqlstore sqlstore.SQLStore) Modules {
return Modules{
Organization: implorganization.NewModule(implorganization.NewStore(sqlstore)),
Preference: implpreference.NewModule(implpreference.NewStore(sqlstore), preferencetypes.NewDefaultPreferenceMap()),
TraceFunnel: impltracefunnel.NewModule(impltracefunnel.NewStore(sqlstore)),
}
}

View File

@@ -76,6 +76,7 @@ func NewSQLMigrationProviderFactories(sqlstore sqlstore.SQLStore) factory.NamedM
sqlmigration.NewDropGroupsFactory(sqlstore),
sqlmigration.NewCreateQuickFiltersFactory(sqlstore),
sqlmigration.NewUpdateQuickFiltersFactory(sqlstore),
sqlmigration.NewAddTraceFunnelsFactory(sqlstore),
)
}