mirror of
https://github.com/SigNoz/signoz.git
synced 2026-04-16 08:50:29 +01:00
Compare commits
17 Commits
public-dir
...
base-path-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17e6d27698 | ||
|
|
09dfadb1ea | ||
|
|
04e01474ff | ||
|
|
6c07b60f06 | ||
|
|
7208777ca6 | ||
|
|
ad3e0527ce | ||
|
|
555dc5881e | ||
|
|
4761fcb57a | ||
|
|
bda93ee286 | ||
|
|
7edc737076 | ||
|
|
4fa306f94f | ||
|
|
c415b2a1d7 | ||
|
|
d513188511 | ||
|
|
e7edc5da82 | ||
|
|
dae7a43a52 | ||
|
|
9fb373e36b | ||
|
|
b01d4d8a74 |
@@ -190,7 +190,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:v0.119.0
|
||||
image: signoz/signoz:v0.118.0
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
# - "6060:6060" # pprof port
|
||||
|
||||
@@ -117,7 +117,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:v0.119.0
|
||||
image: signoz/signoz:v0.118.0
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
volumes:
|
||||
|
||||
@@ -181,7 +181,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:${VERSION:-v0.119.0}
|
||||
image: signoz/signoz:${VERSION:-v0.118.0}
|
||||
container_name: signoz
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
|
||||
@@ -109,7 +109,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:${VERSION:-v0.119.0}
|
||||
image: signoz/signoz:${VERSION:-v0.118.0}
|
||||
container_name: signoz
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
|
||||
1791
docs/api/openapi.yml
1791
docs/api/openapi.yml
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/ee/licensing/httplicensing"
|
||||
"github.com/SigNoz/signoz/ee/query-service/usage"
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
"github.com/SigNoz/signoz/pkg/global"
|
||||
"github.com/SigNoz/signoz/pkg/http/middleware"
|
||||
baseapp "github.com/SigNoz/signoz/pkg/query-service/app"
|
||||
@@ -48,6 +49,7 @@ func NewAPIHandler(opts APIHandlerOptions, signoz *signoz.SigNoz, config signoz.
|
||||
CloudIntegrationsController: opts.CloudIntegrationsController,
|
||||
LogsParsingPipelineController: opts.LogsParsingPipelineController,
|
||||
FluxInterval: opts.FluxInterval,
|
||||
AlertmanagerAPI: alertmanager.NewAPI(signoz.Alertmanager),
|
||||
LicensingAPI: httplicensing.NewLicensingAPI(signoz.Licensing),
|
||||
Signoz: signoz,
|
||||
QueryParserAPI: queryparser.NewAPI(signoz.Instrumentation.ToProviderSettings(), signoz.QueryParser),
|
||||
|
||||
5
frontend/.gitignore
vendored
5
frontend/.gitignore
vendored
@@ -28,4 +28,7 @@ e2e/test-plan/saved-views/
|
||||
e2e/test-plan/service-map/
|
||||
e2e/test-plan/services/
|
||||
e2e/test-plan/traces/
|
||||
e2e/test-plan/user-preferences/
|
||||
e2e/test-plan/user-preferences/
|
||||
|
||||
# Generated by `vite build` — do not commit
|
||||
index.html.gotmpl
|
||||
@@ -2,6 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<base href="[[.BasePath]]" />
|
||||
<meta
|
||||
http-equiv="Cache-Control"
|
||||
content="no-cache, no-store, must-revalidate, max-age: 0"
|
||||
@@ -59,7 +60,7 @@
|
||||
<meta data-react-helmet="true" name="docusaurus_locale" content="en" />
|
||||
<meta data-react-helmet="true" name="docusaurus_tag" content="default" />
|
||||
<meta name="robots" content="noindex" />
|
||||
<link data-react-helmet="true" rel="shortcut icon" href="/favicon.ico" />
|
||||
<link data-react-helmet="true" rel="shortcut icon" href="favicon.ico" />
|
||||
</head>
|
||||
<body data-theme="default">
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
@@ -113,7 +114,7 @@
|
||||
})(document, 'script');
|
||||
}
|
||||
</script>
|
||||
<link rel="stylesheet" href="/css/uPlot.min.css" />
|
||||
<link rel="stylesheet" href="css/uPlot.min.css" />
|
||||
<script type="module" src="./src/index.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import type {
|
||||
InvalidateOptions,
|
||||
QueryClient,
|
||||
QueryFunction,
|
||||
QueryKey,
|
||||
UseQueryOptions,
|
||||
UseQueryResult,
|
||||
} from 'react-query';
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
import type { ErrorType } from '../../../generatedAPIInstance';
|
||||
import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
|
||||
import type { GetAlerts200, RenderErrorResponseDTO } from '../sigNoz.schemas';
|
||||
|
||||
/**
|
||||
* This endpoint returns alerts for the organization
|
||||
* @summary Get alerts
|
||||
*/
|
||||
export const getAlerts = (signal?: AbortSignal) => {
|
||||
return GeneratedAPIInstance<GetAlerts200>({
|
||||
url: `/api/v1/alerts`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetAlertsQueryKey = () => {
|
||||
return [`/api/v1/alerts`] as const;
|
||||
};
|
||||
|
||||
export const getGetAlertsQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getAlerts>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<Awaited<ReturnType<typeof getAlerts>>, TError, TData>;
|
||||
}) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getGetAlertsQueryKey();
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof getAlerts>>> = ({
|
||||
signal,
|
||||
}) => getAlerts(signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAlerts>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetAlertsQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getAlerts>>
|
||||
>;
|
||||
export type GetAlertsQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Get alerts
|
||||
*/
|
||||
|
||||
export function useGetAlerts<
|
||||
TData = Awaited<ReturnType<typeof getAlerts>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<Awaited<ReturnType<typeof getAlerts>>, TError, TData>;
|
||||
}): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetAlertsQueryOptions(options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get alerts
|
||||
*/
|
||||
export const invalidateGetAlerts = async (
|
||||
queryClient: QueryClient,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetAlertsQueryKey() },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
@@ -1,646 +0,0 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import type {
|
||||
InvalidateOptions,
|
||||
MutationFunction,
|
||||
QueryClient,
|
||||
QueryFunction,
|
||||
QueryKey,
|
||||
UseMutationOptions,
|
||||
UseMutationResult,
|
||||
UseQueryOptions,
|
||||
UseQueryResult,
|
||||
} from 'react-query';
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
import type { BodyType, ErrorType } from '../../../generatedAPIInstance';
|
||||
import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
|
||||
import type {
|
||||
ConfigReceiverDTO,
|
||||
CreateChannel201,
|
||||
DeleteChannelByIDPathParameters,
|
||||
GetChannelByID200,
|
||||
GetChannelByIDPathParameters,
|
||||
ListChannels200,
|
||||
RenderErrorResponseDTO,
|
||||
UpdateChannelByIDPathParameters,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
/**
|
||||
* This endpoint lists all notification channels for the organization
|
||||
* @summary List notification channels
|
||||
*/
|
||||
export const listChannels = (signal?: AbortSignal) => {
|
||||
return GeneratedAPIInstance<ListChannels200>({
|
||||
url: `/api/v1/channels`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListChannelsQueryKey = () => {
|
||||
return [`/api/v1/channels`] as const;
|
||||
};
|
||||
|
||||
export const getListChannelsQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listChannels>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listChannels>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
}) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getListChannelsQueryKey();
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof listChannels>>> = ({
|
||||
signal,
|
||||
}) => listChannels(signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listChannels>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type ListChannelsQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listChannels>>
|
||||
>;
|
||||
export type ListChannelsQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List notification channels
|
||||
*/
|
||||
|
||||
export function useListChannels<
|
||||
TData = Awaited<ReturnType<typeof listChannels>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listChannels>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
}): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getListChannelsQueryOptions(options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List notification channels
|
||||
*/
|
||||
export const invalidateListChannels = async (
|
||||
queryClient: QueryClient,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getListChannelsQueryKey() },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint creates a notification channel
|
||||
* @summary Create notification channel
|
||||
*/
|
||||
export const createChannel = (
|
||||
configReceiverDTO: BodyType<ConfigReceiverDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateChannel201>({
|
||||
url: `/api/v1/channels`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: configReceiverDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCreateChannelMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createChannel>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createChannel>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createChannel'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createChannel>>,
|
||||
{ data: BodyType<ConfigReceiverDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return createChannel(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type CreateChannelMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createChannel>>
|
||||
>;
|
||||
export type CreateChannelMutationBody = BodyType<ConfigReceiverDTO>;
|
||||
export type CreateChannelMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Create notification channel
|
||||
*/
|
||||
export const useCreateChannel = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createChannel>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createChannel>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateChannelMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint deletes a notification channel by ID
|
||||
* @summary Delete notification channel
|
||||
*/
|
||||
export const deleteChannelByID = ({ id }: DeleteChannelByIDPathParameters) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/channels/${id}`,
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getDeleteChannelByIDMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteChannelByID>>,
|
||||
TError,
|
||||
{ pathParams: DeleteChannelByIDPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteChannelByID>>,
|
||||
TError,
|
||||
{ pathParams: DeleteChannelByIDPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['deleteChannelByID'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof deleteChannelByID>>,
|
||||
{ pathParams: DeleteChannelByIDPathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return deleteChannelByID(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type DeleteChannelByIDMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof deleteChannelByID>>
|
||||
>;
|
||||
|
||||
export type DeleteChannelByIDMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Delete notification channel
|
||||
*/
|
||||
export const useDeleteChannelByID = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteChannelByID>>,
|
||||
TError,
|
||||
{ pathParams: DeleteChannelByIDPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof deleteChannelByID>>,
|
||||
TError,
|
||||
{ pathParams: DeleteChannelByIDPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getDeleteChannelByIDMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint returns a notification channel by ID
|
||||
* @summary Get notification channel by ID
|
||||
*/
|
||||
export const getChannelByID = (
|
||||
{ id }: GetChannelByIDPathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<GetChannelByID200>({
|
||||
url: `/api/v1/channels/${id}`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetChannelByIDQueryKey = ({
|
||||
id,
|
||||
}: GetChannelByIDPathParameters) => {
|
||||
return [`/api/v1/channels/${id}`] as const;
|
||||
};
|
||||
|
||||
export const getGetChannelByIDQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getChannelByID>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(
|
||||
{ id }: GetChannelByIDPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getChannelByID>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getGetChannelByIDQueryKey({ id });
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof getChannelByID>>> = ({
|
||||
signal,
|
||||
}) => getChannelByID({ id }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!id,
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getChannelByID>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetChannelByIDQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getChannelByID>>
|
||||
>;
|
||||
export type GetChannelByIDQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Get notification channel by ID
|
||||
*/
|
||||
|
||||
export function useGetChannelByID<
|
||||
TData = Awaited<ReturnType<typeof getChannelByID>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(
|
||||
{ id }: GetChannelByIDPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getChannelByID>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetChannelByIDQueryOptions({ id }, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get notification channel by ID
|
||||
*/
|
||||
export const invalidateGetChannelByID = async (
|
||||
queryClient: QueryClient,
|
||||
{ id }: GetChannelByIDPathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetChannelByIDQueryKey({ id }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint updates a notification channel by ID
|
||||
* @summary Update notification channel
|
||||
*/
|
||||
export const updateChannelByID = (
|
||||
{ id }: UpdateChannelByIDPathParameters,
|
||||
configReceiverDTO: BodyType<ConfigReceiverDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/channels/${id}`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: configReceiverDTO,
|
||||
});
|
||||
};
|
||||
|
||||
export const getUpdateChannelByIDMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateChannelByID>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data: BodyType<ConfigReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateChannelByID>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data: BodyType<ConfigReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['updateChannelByID'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof updateChannelByID>>,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data: BodyType<ConfigReceiverDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return updateChannelByID(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UpdateChannelByIDMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateChannelByID>>
|
||||
>;
|
||||
export type UpdateChannelByIDMutationBody = BodyType<ConfigReceiverDTO>;
|
||||
export type UpdateChannelByIDMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Update notification channel
|
||||
*/
|
||||
export const useUpdateChannelByID = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateChannelByID>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data: BodyType<ConfigReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof updateChannelByID>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data: BodyType<ConfigReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getUpdateChannelByIDMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint tests a notification channel by sending a test notification
|
||||
* @summary Test notification channel
|
||||
*/
|
||||
export const testChannel = (
|
||||
configReceiverDTO: BodyType<ConfigReceiverDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/channels/test`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: configReceiverDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getTestChannelMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['testChannel'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
{ data: BodyType<ConfigReceiverDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return testChannel(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type TestChannelMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof testChannel>>
|
||||
>;
|
||||
export type TestChannelMutationBody = BodyType<ConfigReceiverDTO>;
|
||||
export type TestChannelMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Test notification channel
|
||||
*/
|
||||
export const useTestChannel = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getTestChannelMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Deprecated: use /api/v1/channels/test instead
|
||||
* @deprecated
|
||||
* @summary Test notification channel (deprecated)
|
||||
*/
|
||||
export const testChannelDeprecated = (
|
||||
configReceiverDTO: BodyType<ConfigReceiverDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/testChannel`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: configReceiverDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getTestChannelDeprecatedMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['testChannelDeprecated'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
{ data: BodyType<ConfigReceiverDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return testChannelDeprecated(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type TestChannelDeprecatedMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>
|
||||
>;
|
||||
export type TestChannelDeprecatedMutationBody = BodyType<ConfigReceiverDTO>;
|
||||
export type TestChannelDeprecatedMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @summary Test notification channel (deprecated)
|
||||
*/
|
||||
export const useTestChannelDeprecated = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data: BodyType<ConfigReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getTestChannelDeprecatedMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
@@ -1,482 +0,0 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import type {
|
||||
InvalidateOptions,
|
||||
MutationFunction,
|
||||
QueryClient,
|
||||
QueryFunction,
|
||||
QueryKey,
|
||||
UseMutationOptions,
|
||||
UseMutationResult,
|
||||
UseQueryOptions,
|
||||
UseQueryResult,
|
||||
} from 'react-query';
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
import type { BodyType, ErrorType } from '../../../generatedAPIInstance';
|
||||
import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
|
||||
import type {
|
||||
AlertmanagertypesPostableRoutePolicyDTO,
|
||||
CreateRoutePolicy201,
|
||||
DeleteRoutePolicyByIDPathParameters,
|
||||
GetAllRoutePolicies200,
|
||||
GetRoutePolicyByID200,
|
||||
GetRoutePolicyByIDPathParameters,
|
||||
RenderErrorResponseDTO,
|
||||
UpdateRoutePolicy200,
|
||||
UpdateRoutePolicyPathParameters,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
/**
|
||||
* This endpoint lists all route policies for the organization
|
||||
* @summary List route policies
|
||||
*/
|
||||
export const getAllRoutePolicies = (signal?: AbortSignal) => {
|
||||
return GeneratedAPIInstance<GetAllRoutePolicies200>({
|
||||
url: `/api/v1/route_policies`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetAllRoutePoliciesQueryKey = () => {
|
||||
return [`/api/v1/route_policies`] as const;
|
||||
};
|
||||
|
||||
export const getGetAllRoutePoliciesQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getAllRoutePolicies>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAllRoutePolicies>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
}) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getGetAllRoutePoliciesQueryKey();
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof getAllRoutePolicies>>
|
||||
> = ({ signal }) => getAllRoutePolicies(signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAllRoutePolicies>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetAllRoutePoliciesQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getAllRoutePolicies>>
|
||||
>;
|
||||
export type GetAllRoutePoliciesQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List route policies
|
||||
*/
|
||||
|
||||
export function useGetAllRoutePolicies<
|
||||
TData = Awaited<ReturnType<typeof getAllRoutePolicies>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAllRoutePolicies>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
}): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetAllRoutePoliciesQueryOptions(options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List route policies
|
||||
*/
|
||||
export const invalidateGetAllRoutePolicies = async (
|
||||
queryClient: QueryClient,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetAllRoutePoliciesQueryKey() },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint creates a route policy
|
||||
* @summary Create route policy
|
||||
*/
|
||||
export const createRoutePolicy = (
|
||||
alertmanagertypesPostableRoutePolicyDTO: BodyType<AlertmanagertypesPostableRoutePolicyDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateRoutePolicy201>({
|
||||
url: `/api/v1/route_policies`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: alertmanagertypesPostableRoutePolicyDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCreateRoutePolicyMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createRoutePolicy>>,
|
||||
TError,
|
||||
{ data: BodyType<AlertmanagertypesPostableRoutePolicyDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createRoutePolicy>>,
|
||||
TError,
|
||||
{ data: BodyType<AlertmanagertypesPostableRoutePolicyDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createRoutePolicy'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createRoutePolicy>>,
|
||||
{ data: BodyType<AlertmanagertypesPostableRoutePolicyDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return createRoutePolicy(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type CreateRoutePolicyMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createRoutePolicy>>
|
||||
>;
|
||||
export type CreateRoutePolicyMutationBody = BodyType<AlertmanagertypesPostableRoutePolicyDTO>;
|
||||
export type CreateRoutePolicyMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Create route policy
|
||||
*/
|
||||
export const useCreateRoutePolicy = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createRoutePolicy>>,
|
||||
TError,
|
||||
{ data: BodyType<AlertmanagertypesPostableRoutePolicyDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createRoutePolicy>>,
|
||||
TError,
|
||||
{ data: BodyType<AlertmanagertypesPostableRoutePolicyDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateRoutePolicyMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint deletes a route policy by ID
|
||||
* @summary Delete route policy
|
||||
*/
|
||||
export const deleteRoutePolicyByID = ({
|
||||
id,
|
||||
}: DeleteRoutePolicyByIDPathParameters) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/route_policies/${id}`,
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getDeleteRoutePolicyByIDMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteRoutePolicyByID>>,
|
||||
TError,
|
||||
{ pathParams: DeleteRoutePolicyByIDPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteRoutePolicyByID>>,
|
||||
TError,
|
||||
{ pathParams: DeleteRoutePolicyByIDPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['deleteRoutePolicyByID'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof deleteRoutePolicyByID>>,
|
||||
{ pathParams: DeleteRoutePolicyByIDPathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return deleteRoutePolicyByID(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type DeleteRoutePolicyByIDMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof deleteRoutePolicyByID>>
|
||||
>;
|
||||
|
||||
export type DeleteRoutePolicyByIDMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Delete route policy
|
||||
*/
|
||||
export const useDeleteRoutePolicyByID = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteRoutePolicyByID>>,
|
||||
TError,
|
||||
{ pathParams: DeleteRoutePolicyByIDPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof deleteRoutePolicyByID>>,
|
||||
TError,
|
||||
{ pathParams: DeleteRoutePolicyByIDPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getDeleteRoutePolicyByIDMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint returns a route policy by ID
|
||||
* @summary Get route policy by ID
|
||||
*/
|
||||
export const getRoutePolicyByID = (
|
||||
{ id }: GetRoutePolicyByIDPathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<GetRoutePolicyByID200>({
|
||||
url: `/api/v1/route_policies/${id}`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetRoutePolicyByIDQueryKey = ({
|
||||
id,
|
||||
}: GetRoutePolicyByIDPathParameters) => {
|
||||
return [`/api/v1/route_policies/${id}`] as const;
|
||||
};
|
||||
|
||||
export const getGetRoutePolicyByIDQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getRoutePolicyByID>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(
|
||||
{ id }: GetRoutePolicyByIDPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getRoutePolicyByID>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getGetRoutePolicyByIDQueryKey({ id });
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof getRoutePolicyByID>>
|
||||
> = ({ signal }) => getRoutePolicyByID({ id }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!id,
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getRoutePolicyByID>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetRoutePolicyByIDQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getRoutePolicyByID>>
|
||||
>;
|
||||
export type GetRoutePolicyByIDQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Get route policy by ID
|
||||
*/
|
||||
|
||||
export function useGetRoutePolicyByID<
|
||||
TData = Awaited<ReturnType<typeof getRoutePolicyByID>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(
|
||||
{ id }: GetRoutePolicyByIDPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getRoutePolicyByID>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetRoutePolicyByIDQueryOptions({ id }, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get route policy by ID
|
||||
*/
|
||||
export const invalidateGetRoutePolicyByID = async (
|
||||
queryClient: QueryClient,
|
||||
{ id }: GetRoutePolicyByIDPathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetRoutePolicyByIDQueryKey({ id }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint updates a route policy by ID
|
||||
* @summary Update route policy
|
||||
*/
|
||||
export const updateRoutePolicy = (
|
||||
{ id }: UpdateRoutePolicyPathParameters,
|
||||
alertmanagertypesPostableRoutePolicyDTO: BodyType<AlertmanagertypesPostableRoutePolicyDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<UpdateRoutePolicy200>({
|
||||
url: `/api/v1/route_policies/${id}`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: alertmanagertypesPostableRoutePolicyDTO,
|
||||
});
|
||||
};
|
||||
|
||||
export const getUpdateRoutePolicyMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateRoutePolicy>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateRoutePolicyPathParameters;
|
||||
data: BodyType<AlertmanagertypesPostableRoutePolicyDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateRoutePolicy>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateRoutePolicyPathParameters;
|
||||
data: BodyType<AlertmanagertypesPostableRoutePolicyDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['updateRoutePolicy'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof updateRoutePolicy>>,
|
||||
{
|
||||
pathParams: UpdateRoutePolicyPathParameters;
|
||||
data: BodyType<AlertmanagertypesPostableRoutePolicyDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return updateRoutePolicy(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UpdateRoutePolicyMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateRoutePolicy>>
|
||||
>;
|
||||
export type UpdateRoutePolicyMutationBody = BodyType<AlertmanagertypesPostableRoutePolicyDTO>;
|
||||
export type UpdateRoutePolicyMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Update route policy
|
||||
*/
|
||||
export const useUpdateRoutePolicy = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateRoutePolicy>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateRoutePolicyPathParameters;
|
||||
data: BodyType<AlertmanagertypesPostableRoutePolicyDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof updateRoutePolicy>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateRoutePolicyPathParameters;
|
||||
data: BodyType<AlertmanagertypesPostableRoutePolicyDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getUpdateRoutePolicyMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
interceptorRejected,
|
||||
interceptorsRequestBasePath,
|
||||
interceptorsRequestResponse,
|
||||
interceptorsResponse,
|
||||
} from 'api';
|
||||
@@ -17,6 +18,7 @@ export const GeneratedAPIInstance = <T>(
|
||||
return generatedAPIAxiosInstance({ ...config }).then(({ data }) => data);
|
||||
};
|
||||
|
||||
generatedAPIAxiosInstance.interceptors.request.use(interceptorsRequestBasePath);
|
||||
generatedAPIAxiosInstance.interceptors.request.use(interceptorsRequestResponse);
|
||||
generatedAPIAxiosInstance.interceptors.response.use(
|
||||
interceptorsResponse,
|
||||
|
||||
@@ -11,6 +11,7 @@ import axios, {
|
||||
import { ENVIRONMENT } from 'constants/env';
|
||||
import { Events } from 'constants/events';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { getBasePath } from 'utils/getBasePath';
|
||||
import { eventEmitter } from 'utils/getEventEmitter';
|
||||
|
||||
import apiV1, { apiAlertManager, apiV2, apiV3, apiV4, apiV5 } from './apiV1';
|
||||
@@ -67,6 +68,28 @@ export const interceptorsRequestResponse = (
|
||||
return value;
|
||||
};
|
||||
|
||||
// Prepends the runtime base path to outgoing requests so API calls work under
|
||||
// a URL prefix (e.g. /signoz/api/v1/…). No-op for root deployments and dev
|
||||
// (dev baseURL is a full http:// URL, not an absolute path).
|
||||
export const interceptorsRequestBasePath = (
|
||||
value: InternalAxiosRequestConfig,
|
||||
): InternalAxiosRequestConfig => {
|
||||
const basePath = getBasePath();
|
||||
if (basePath === '/') {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (value.baseURL?.startsWith('/')) {
|
||||
// Named instances: baseURL='/api/v1/' → '/signoz/api/v1/'
|
||||
value.baseURL = basePath + value.baseURL.slice(1);
|
||||
} else if (!value.baseURL && value.url?.startsWith('/')) {
|
||||
// Generated instance: baseURL is '' in prod, path is in url
|
||||
value.url = basePath + value.url.slice(1);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
export const interceptorRejected = async (
|
||||
value: AxiosResponse<any>,
|
||||
): Promise<AxiosResponse<any>> => {
|
||||
@@ -133,6 +156,7 @@ const instance = axios.create({
|
||||
});
|
||||
|
||||
instance.interceptors.request.use(interceptorsRequestResponse);
|
||||
instance.interceptors.request.use(interceptorsRequestBasePath);
|
||||
instance.interceptors.response.use(interceptorsResponse, interceptorRejected);
|
||||
|
||||
export const AxiosAlertManagerInstance = axios.create({
|
||||
@@ -147,6 +171,7 @@ ApiV2Instance.interceptors.response.use(
|
||||
interceptorRejected,
|
||||
);
|
||||
ApiV2Instance.interceptors.request.use(interceptorsRequestResponse);
|
||||
ApiV2Instance.interceptors.request.use(interceptorsRequestBasePath);
|
||||
|
||||
// axios V3
|
||||
export const ApiV3Instance = axios.create({
|
||||
@@ -158,6 +183,7 @@ ApiV3Instance.interceptors.response.use(
|
||||
interceptorRejected,
|
||||
);
|
||||
ApiV3Instance.interceptors.request.use(interceptorsRequestResponse);
|
||||
ApiV3Instance.interceptors.request.use(interceptorsRequestBasePath);
|
||||
//
|
||||
|
||||
// axios V4
|
||||
@@ -170,6 +196,7 @@ ApiV4Instance.interceptors.response.use(
|
||||
interceptorRejected,
|
||||
);
|
||||
ApiV4Instance.interceptors.request.use(interceptorsRequestResponse);
|
||||
ApiV4Instance.interceptors.request.use(interceptorsRequestBasePath);
|
||||
//
|
||||
|
||||
// axios V5
|
||||
@@ -182,6 +209,7 @@ ApiV5Instance.interceptors.response.use(
|
||||
interceptorRejected,
|
||||
);
|
||||
ApiV5Instance.interceptors.request.use(interceptorsRequestResponse);
|
||||
ApiV5Instance.interceptors.request.use(interceptorsRequestBasePath);
|
||||
//
|
||||
|
||||
// axios Base
|
||||
@@ -194,6 +222,7 @@ LogEventAxiosInstance.interceptors.response.use(
|
||||
interceptorRejectedBase,
|
||||
);
|
||||
LogEventAxiosInstance.interceptors.request.use(interceptorsRequestResponse);
|
||||
LogEventAxiosInstance.interceptors.request.use(interceptorsRequestBasePath);
|
||||
//
|
||||
|
||||
AxiosAlertManagerInstance.interceptors.response.use(
|
||||
@@ -201,6 +230,7 @@ AxiosAlertManagerInstance.interceptors.response.use(
|
||||
interceptorRejected,
|
||||
);
|
||||
AxiosAlertManagerInstance.interceptors.request.use(interceptorsRequestResponse);
|
||||
AxiosAlertManagerInstance.interceptors.request.use(interceptorsRequestBasePath);
|
||||
|
||||
export { apiV1 };
|
||||
export default instance;
|
||||
|
||||
@@ -20,11 +20,11 @@ import { ViewProps } from 'types/api/saveViews/types';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { USER_ROLES } from 'types/roles';
|
||||
|
||||
import circusTentUrl from '@/assets/Icons/circus-tent.svg';
|
||||
import eightBallUrl from '@/assets/Icons/eight-ball.svg';
|
||||
import floppyDiscUrl from '@/assets/Icons/floppy-disc.svg';
|
||||
import logsUrl from '@/assets/Icons/logs.svg';
|
||||
|
||||
import { getItemIcon } from '../constants';
|
||||
|
||||
export default function SavedViews({
|
||||
onUpdateChecklistDoneItem,
|
||||
loadingUserPreferences,
|
||||
@@ -229,7 +229,7 @@ export default function SavedViews({
|
||||
>
|
||||
<div className="saved-view-item-name-container home-data-item-name-container">
|
||||
<img
|
||||
src={getItemIcon(String(view.id))}
|
||||
src={view.id % 2 === 0 ? eightBallUrl : circusTentUrl}
|
||||
alt="alert-rules"
|
||||
className="alert-rules-img"
|
||||
/>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// hippa.svg and soc2.svg do not exist in src/assets — suppressed until assets are added
|
||||
import { Dot } from 'lucide-react';
|
||||
|
||||
import './OnboardingFooter.styles.scss';
|
||||
@@ -12,7 +13,6 @@ export function OnboardingFooter(): JSX.Element {
|
||||
className="footer-content"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{/* hippa.svg does not exist in src/assets — suppressed until asset is added */}
|
||||
{/* eslint-disable-next-line rulesdir/no-unsupported-asset-pattern */}
|
||||
<img src="/logos/hippa.svg" alt="HIPPA" className="footer-logo" />
|
||||
<span className="footer-text">HIPPA</span>
|
||||
@@ -24,7 +24,6 @@ export function OnboardingFooter(): JSX.Element {
|
||||
className="footer-content"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{/* soc2.svg does not exist in src/assets — suppressed until asset is added */}
|
||||
{/* eslint-disable-next-line rulesdir/no-unsupported-asset-pattern */}
|
||||
<img src="/logos/soc2.svg" alt="SOC2" className="footer-logo" />
|
||||
<span className="footer-text">SOC2</span>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { createBrowserHistory } from 'history';
|
||||
import { getBasePath } from 'utils/getBasePath';
|
||||
|
||||
export default createBrowserHistory();
|
||||
export default createBrowserHistory({ basename: getBasePath() });
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useCallback } from 'react';
|
||||
import { Button } from 'antd';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
|
||||
import history from 'lib/history';
|
||||
import { Home, LifeBuoy } from 'lucide-react';
|
||||
import { handleContactSupport } from 'pages/Integrations/utils';
|
||||
|
||||
@@ -11,8 +12,9 @@ import './ErrorBoundaryFallback.styles.scss';
|
||||
|
||||
function ErrorBoundaryFallback(): JSX.Element {
|
||||
const handleReload = (): void => {
|
||||
// Go to home page
|
||||
window.location.href = ROUTES.HOME;
|
||||
// Use history.push so the navigation stays within the base path prefix
|
||||
// (window.location.href would strip any /signoz/ prefix).
|
||||
history.push(ROUTES.HOME);
|
||||
};
|
||||
|
||||
const { isCloudUser: isCloudUserVal } = useGetTenantLicense();
|
||||
|
||||
50
frontend/src/utils/__tests__/getBasePath.test.ts
Normal file
50
frontend/src/utils/__tests__/getBasePath.test.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { getBasePath } from 'utils/getBasePath';
|
||||
|
||||
/**
|
||||
* Contract tests for getBasePath().
|
||||
*
|
||||
* These lock down the exact DOM-reading contract so that any future change to
|
||||
* the utility (or to how index.html injects the <base> tag) surfaces
|
||||
* immediately as a test failure.
|
||||
*/
|
||||
describe('getBasePath', () => {
|
||||
afterEach(() => {
|
||||
// Remove any <base> elements added during the test.
|
||||
document.head.querySelectorAll('base').forEach((el) => el.remove());
|
||||
});
|
||||
|
||||
it('returns the href from the <base> tag when present', () => {
|
||||
const base = document.createElement('base');
|
||||
base.setAttribute('href', '/signoz/');
|
||||
document.head.appendChild(base);
|
||||
|
||||
expect(getBasePath()).toBe('/signoz/');
|
||||
});
|
||||
|
||||
it('returns "/" when no <base> tag exists in the document', () => {
|
||||
expect(getBasePath()).toBe('/');
|
||||
});
|
||||
|
||||
it('returns "/" when the <base> tag has no href attribute', () => {
|
||||
const base = document.createElement('base');
|
||||
document.head.appendChild(base);
|
||||
|
||||
expect(getBasePath()).toBe('/');
|
||||
});
|
||||
|
||||
it('returns the href unchanged when it already has a trailing slash', () => {
|
||||
const base = document.createElement('base');
|
||||
base.setAttribute('href', '/my/nested/path/');
|
||||
document.head.appendChild(base);
|
||||
|
||||
expect(getBasePath()).toBe('/my/nested/path/');
|
||||
});
|
||||
|
||||
it('appends a trailing slash when the href is missing one', () => {
|
||||
const base = document.createElement('base');
|
||||
base.setAttribute('href', '/signoz');
|
||||
document.head.appendChild(base);
|
||||
|
||||
expect(getBasePath()).toBe('/signoz/');
|
||||
});
|
||||
});
|
||||
17
frontend/src/utils/getBasePath.ts
Normal file
17
frontend/src/utils/getBasePath.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Returns the base path for this SigNoz deployment by reading the
|
||||
* `<base href>` element injected into index.html by the Go backend at
|
||||
* serve time.
|
||||
*
|
||||
* Always returns a string ending with `/` (e.g. `/`, `/signoz/`).
|
||||
* Falls back to `/` when no `<base>` element is present so the app
|
||||
* behaves correctly in local Vite dev and unit-test environments.
|
||||
*
|
||||
* @internal — consume through `src/lib/history` and the axios interceptor;
|
||||
* do not read `<base>` directly anywhere else in the codebase.
|
||||
*/
|
||||
export function getBasePath(): string {
|
||||
const href = document.querySelector('base')?.getAttribute('href') ?? '/';
|
||||
// Trailing slash is required for relative asset resolution and API prefixing.
|
||||
return href.endsWith('/') ? href : `${href}/`;
|
||||
}
|
||||
@@ -10,6 +10,18 @@ import { createHtmlPlugin } from 'vite-plugin-html';
|
||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
|
||||
// In dev the Go backend is not involved, so replace the [[.BasePath]] placeholder
|
||||
// with "/" so relative assets resolve correctly from the Vite dev server.
|
||||
function devBasePathPlugin(): Plugin {
|
||||
return {
|
||||
name: 'dev-base-path',
|
||||
apply: 'serve',
|
||||
transformIndexHtml(html): string {
|
||||
return html.replace('[[.BasePath]]', '/');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function rawMarkdownPlugin(): Plugin {
|
||||
return {
|
||||
name: 'raw-markdown',
|
||||
@@ -32,6 +44,7 @@ export default defineConfig(
|
||||
const plugins = [
|
||||
tsconfigPaths(),
|
||||
rawMarkdownPlugin(),
|
||||
devBasePathPlugin(),
|
||||
react(),
|
||||
createHtmlPlugin({
|
||||
inject: {
|
||||
@@ -124,6 +137,7 @@ export default defineConfig(
|
||||
'process.env.TUNNEL_DOMAIN': JSON.stringify(env.VITE_TUNNEL_DOMAIN),
|
||||
'process.env.DOCS_BASE_URL': JSON.stringify(env.VITE_DOCS_BASE_URL),
|
||||
},
|
||||
base: './',
|
||||
build: {
|
||||
sourcemap: true,
|
||||
outDir: 'build',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package signozalertmanager
|
||||
package alertmanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/http/render"
|
||||
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
||||
@@ -16,15 +15,17 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
alertmanager alertmanager.Alertmanager
|
||||
type API struct {
|
||||
alertmanager Alertmanager
|
||||
}
|
||||
|
||||
func NewHandler(alertmanager alertmanager.Alertmanager) alertmanager.Handler {
|
||||
return &handler{alertmanager: alertmanager}
|
||||
func NewAPI(alertmanager Alertmanager) *API {
|
||||
return &API{
|
||||
alertmanager: alertmanager,
|
||||
}
|
||||
}
|
||||
|
||||
func (handler *handler) GetAlerts(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) GetAlerts(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -40,7 +41,7 @@ func (handler *handler) GetAlerts(rw http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
alerts, err := handler.alertmanager.GetAlerts(ctx, claims.OrgID, params)
|
||||
alerts, err := api.alertmanager.GetAlerts(ctx, claims.OrgID, params)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -49,7 +50,7 @@ func (handler *handler) GetAlerts(rw http.ResponseWriter, req *http.Request) {
|
||||
render.Success(rw, http.StatusOK, alerts)
|
||||
}
|
||||
|
||||
func (handler *handler) TestReceiver(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) TestReceiver(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -72,7 +73,7 @@ func (handler *handler) TestReceiver(rw http.ResponseWriter, req *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
err = handler.alertmanager.TestReceiver(ctx, claims.OrgID, receiver)
|
||||
err = api.alertmanager.TestReceiver(ctx, claims.OrgID, receiver)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -81,7 +82,7 @@ func (handler *handler) TestReceiver(rw http.ResponseWriter, req *http.Request)
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) ListChannels(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) ListChannels(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -91,7 +92,7 @@ func (handler *handler) ListChannels(rw http.ResponseWriter, req *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
channels, err := handler.alertmanager.ListChannels(ctx, claims.OrgID)
|
||||
channels, err := api.alertmanager.ListChannels(ctx, claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -105,11 +106,11 @@ func (handler *handler) ListChannels(rw http.ResponseWriter, req *http.Request)
|
||||
render.Success(rw, http.StatusOK, channels)
|
||||
}
|
||||
|
||||
func (handler *handler) ListAllChannels(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) ListAllChannels(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
channels, err := handler.alertmanager.ListAllChannels(ctx)
|
||||
channels, err := api.alertmanager.ListAllChannels(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -118,7 +119,7 @@ func (handler *handler) ListAllChannels(rw http.ResponseWriter, req *http.Reques
|
||||
render.Success(rw, http.StatusOK, channels)
|
||||
}
|
||||
|
||||
func (handler *handler) GetChannelByID(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) GetChannelByID(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -146,7 +147,7 @@ func (handler *handler) GetChannelByID(rw http.ResponseWriter, req *http.Request
|
||||
return
|
||||
}
|
||||
|
||||
channel, err := handler.alertmanager.GetChannelByID(ctx, claims.OrgID, id)
|
||||
channel, err := api.alertmanager.GetChannelByID(ctx, claims.OrgID, id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -155,7 +156,7 @@ func (handler *handler) GetChannelByID(rw http.ResponseWriter, req *http.Request
|
||||
render.Success(rw, http.StatusOK, channel)
|
||||
}
|
||||
|
||||
func (handler *handler) UpdateChannelByID(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) UpdateChannelByID(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -196,7 +197,7 @@ func (handler *handler) UpdateChannelByID(rw http.ResponseWriter, req *http.Requ
|
||||
return
|
||||
}
|
||||
|
||||
err = handler.alertmanager.UpdateChannelByReceiverAndID(ctx, claims.OrgID, receiver, id)
|
||||
err = api.alertmanager.UpdateChannelByReceiverAndID(ctx, claims.OrgID, receiver, id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -205,7 +206,7 @@ func (handler *handler) UpdateChannelByID(rw http.ResponseWriter, req *http.Requ
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) DeleteChannelByID(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) DeleteChannelByID(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -233,7 +234,7 @@ func (handler *handler) DeleteChannelByID(rw http.ResponseWriter, req *http.Requ
|
||||
return
|
||||
}
|
||||
|
||||
err = handler.alertmanager.DeleteChannelByID(ctx, claims.OrgID, id)
|
||||
err = api.alertmanager.DeleteChannelByID(ctx, claims.OrgID, id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -242,7 +243,7 @@ func (handler *handler) DeleteChannelByID(rw http.ResponseWriter, req *http.Requ
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) CreateChannel(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) CreateChannel(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -265,7 +266,7 @@ func (handler *handler) CreateChannel(rw http.ResponseWriter, req *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
channel, err := handler.alertmanager.CreateChannel(ctx, claims.OrgID, receiver)
|
||||
channel, err := api.alertmanager.CreateChannel(ctx, claims.OrgID, receiver)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -274,7 +275,7 @@ func (handler *handler) CreateChannel(rw http.ResponseWriter, req *http.Request)
|
||||
render.Success(rw, http.StatusCreated, channel)
|
||||
}
|
||||
|
||||
func (handler *handler) CreateRoutePolicy(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) CreateRoutePolicy(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -299,7 +300,7 @@ func (handler *handler) CreateRoutePolicy(rw http.ResponseWriter, req *http.Requ
|
||||
return
|
||||
}
|
||||
|
||||
result, err := handler.alertmanager.CreateRoutePolicy(ctx, &policy)
|
||||
result, err := api.alertmanager.CreateRoutePolicy(ctx, &policy)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -308,11 +309,11 @@ func (handler *handler) CreateRoutePolicy(rw http.ResponseWriter, req *http.Requ
|
||||
render.Success(rw, http.StatusCreated, result)
|
||||
}
|
||||
|
||||
func (handler *handler) GetAllRoutePolicies(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) GetAllRoutePolicies(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
policies, err := handler.alertmanager.GetAllRoutePolicies(ctx)
|
||||
policies, err := api.alertmanager.GetAllRoutePolicies(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -321,7 +322,7 @@ func (handler *handler) GetAllRoutePolicies(rw http.ResponseWriter, req *http.Re
|
||||
render.Success(rw, http.StatusOK, policies)
|
||||
}
|
||||
|
||||
func (handler *handler) GetRoutePolicyByID(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) GetRoutePolicyByID(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -332,7 +333,7 @@ func (handler *handler) GetRoutePolicyByID(rw http.ResponseWriter, req *http.Req
|
||||
return
|
||||
}
|
||||
|
||||
policy, err := handler.alertmanager.GetRoutePolicyByID(ctx, policyID)
|
||||
policy, err := api.alertmanager.GetRoutePolicyByID(ctx, policyID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -341,7 +342,7 @@ func (handler *handler) GetRoutePolicyByID(rw http.ResponseWriter, req *http.Req
|
||||
render.Success(rw, http.StatusOK, policy)
|
||||
}
|
||||
|
||||
func (handler *handler) DeleteRoutePolicyByID(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) DeleteRoutePolicyByID(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -352,7 +353,7 @@ func (handler *handler) DeleteRoutePolicyByID(rw http.ResponseWriter, req *http.
|
||||
return
|
||||
}
|
||||
|
||||
err := handler.alertmanager.DeleteRoutePolicyByID(ctx, policyID)
|
||||
err := api.alertmanager.DeleteRoutePolicyByID(ctx, policyID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -361,7 +362,7 @@ func (handler *handler) DeleteRoutePolicyByID(rw http.ResponseWriter, req *http.
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) UpdateRoutePolicy(rw http.ResponseWriter, req *http.Request) {
|
||||
func (api *API) UpdateRoutePolicy(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -391,7 +392,7 @@ func (handler *handler) UpdateRoutePolicy(rw http.ResponseWriter, req *http.Requ
|
||||
return
|
||||
}
|
||||
|
||||
result, err := handler.alertmanager.UpdateRoutePolicyByID(ctx, policyID, &policy)
|
||||
result, err := api.alertmanager.UpdateRoutePolicyByID(ctx, policyID, &policy)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -1,31 +0,0 @@
|
||||
package alertmanager
|
||||
|
||||
import "net/http"
|
||||
|
||||
type Handler interface {
|
||||
GetAlerts(http.ResponseWriter, *http.Request)
|
||||
|
||||
TestReceiver(http.ResponseWriter, *http.Request)
|
||||
|
||||
ListChannels(http.ResponseWriter, *http.Request)
|
||||
|
||||
ListAllChannels(http.ResponseWriter, *http.Request)
|
||||
|
||||
GetChannelByID(http.ResponseWriter, *http.Request)
|
||||
|
||||
CreateChannel(http.ResponseWriter, *http.Request)
|
||||
|
||||
UpdateChannelByID(http.ResponseWriter, *http.Request)
|
||||
|
||||
DeleteChannelByID(http.ResponseWriter, *http.Request)
|
||||
|
||||
GetAllRoutePolicies(http.ResponseWriter, *http.Request)
|
||||
|
||||
GetRoutePolicyByID(http.ResponseWriter, *http.Request)
|
||||
|
||||
CreateRoutePolicy(http.ResponseWriter, *http.Request)
|
||||
|
||||
UpdateRoutePolicy(http.ResponseWriter, *http.Request)
|
||||
|
||||
DeleteRoutePolicyByID(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
@@ -223,8 +223,6 @@ func (r *provider) Match(ctx context.Context, orgID string, ruleID string, set m
|
||||
for _, route := range expressionRoutes {
|
||||
evaluateExpr, err := r.evaluateExpr(ctx, route.Expression, set)
|
||||
if err != nil {
|
||||
//nolint:sloglint
|
||||
r.settings.Logger().WarnContext(ctx, "failed to evaluate route policy expression", errors.Attr(err), slog.String("rule.id", ruleID))
|
||||
continue
|
||||
}
|
||||
if evaluateExpr {
|
||||
@@ -300,7 +298,7 @@ func (r *provider) convertLabelSetToEnv(ctx context.Context, labelSet model.Labe
|
||||
func (r *provider) evaluateExpr(ctx context.Context, expression string, labelSet model.LabelSet) (bool, error) {
|
||||
env := r.convertLabelSetToEnv(ctx, labelSet)
|
||||
|
||||
program, err := expr.Compile(expression, expr.Env(env), expr.AllowUndefinedVariables())
|
||||
program, err := expr.Compile(expression, expr.Env(env))
|
||||
if err != nil {
|
||||
return false, errors.NewInternalf(errors.CodeInternal, "error compiling route policy %s: %v", expression, err)
|
||||
}
|
||||
|
||||
@@ -644,22 +644,6 @@ func TestProvider_EvaluateExpression(t *testing.T) {
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "nonexistent key OR check",
|
||||
expression: `threshold.name = 'warning' OR ruleId = 'rule1'`,
|
||||
labelSet: model.LabelSet{
|
||||
"threshold.name": "warning",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "nonexistent key && check",
|
||||
expression: `threshold.name = 'warning' && nonexistent = 'auth'`,
|
||||
labelSet: model.LabelSet{
|
||||
"threshold.name": "warning",
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -309,8 +309,8 @@ func (provider *provider) CreateRoutePolicy(ctx context.Context, routeRequest *a
|
||||
return &alertmanagertypes.GettableRoutePolicy{
|
||||
PostableRoutePolicy: *routeRequest,
|
||||
ID: route.ID.StringValue(),
|
||||
CreatedAt: route.CreatedAt,
|
||||
UpdatedAt: route.UpdatedAt,
|
||||
CreatedAt: &route.CreatedAt,
|
||||
UpdatedAt: &route.UpdatedAt,
|
||||
CreatedBy: &route.CreatedBy,
|
||||
UpdatedBy: &route.UpdatedBy,
|
||||
}, nil
|
||||
@@ -365,8 +365,8 @@ func (provider *provider) CreateRoutePolicies(ctx context.Context, routeRequests
|
||||
results = append(results, &alertmanagertypes.GettableRoutePolicy{
|
||||
PostableRoutePolicy: *routeRequest,
|
||||
ID: route.ID.StringValue(),
|
||||
CreatedAt: route.CreatedAt,
|
||||
UpdatedAt: route.UpdatedAt,
|
||||
CreatedAt: &route.CreatedAt,
|
||||
UpdatedAt: &route.UpdatedAt,
|
||||
CreatedBy: &route.CreatedBy,
|
||||
UpdatedBy: &route.UpdatedBy,
|
||||
})
|
||||
@@ -405,8 +405,8 @@ func (provider *provider) GetRoutePolicyByID(ctx context.Context, routeID string
|
||||
Tags: route.Tags,
|
||||
},
|
||||
ID: route.ID.StringValue(),
|
||||
CreatedAt: route.CreatedAt,
|
||||
UpdatedAt: route.UpdatedAt,
|
||||
CreatedAt: &route.CreatedAt,
|
||||
UpdatedAt: &route.UpdatedAt,
|
||||
CreatedBy: &route.CreatedBy,
|
||||
UpdatedBy: &route.UpdatedBy,
|
||||
}, nil
|
||||
@@ -439,8 +439,8 @@ func (provider *provider) GetAllRoutePolicies(ctx context.Context) ([]*alertmana
|
||||
Tags: route.Tags,
|
||||
},
|
||||
ID: route.ID.StringValue(),
|
||||
CreatedAt: route.CreatedAt,
|
||||
UpdatedAt: route.UpdatedAt,
|
||||
CreatedAt: &route.CreatedAt,
|
||||
UpdatedAt: &route.UpdatedAt,
|
||||
CreatedBy: &route.CreatedBy,
|
||||
UpdatedBy: &route.UpdatedBy,
|
||||
})
|
||||
@@ -508,8 +508,8 @@ func (provider *provider) UpdateRoutePolicyByID(ctx context.Context, routeID str
|
||||
return &alertmanagertypes.GettableRoutePolicy{
|
||||
PostableRoutePolicy: *route,
|
||||
ID: updatedRoute.ID.StringValue(),
|
||||
CreatedAt: updatedRoute.CreatedAt,
|
||||
UpdatedAt: updatedRoute.UpdatedAt,
|
||||
CreatedAt: &updatedRoute.CreatedAt,
|
||||
UpdatedAt: &updatedRoute.UpdatedAt,
|
||||
CreatedBy: &updatedRoute.CreatedBy,
|
||||
UpdatedBy: &updatedRoute.UpdatedBy,
|
||||
}, nil
|
||||
|
||||
@@ -1,235 +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/alertmanagertypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (provider *provider) addAlertmanagerRoutes(router *mux.Router) error {
|
||||
if err := router.Handle("/api/v1/channels", handler.New(provider.authZ.ViewAccess(provider.alertmanagerHandler.ListChannels), handler.OpenAPIDef{
|
||||
ID: "ListChannels",
|
||||
Tags: []string{"channels"},
|
||||
Summary: "List notification channels",
|
||||
Description: "This endpoint lists all notification channels for the organization",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: make([]*alertmanagertypes.Channel, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/channels/{id}", handler.New(provider.authZ.ViewAccess(provider.alertmanagerHandler.GetChannelByID), handler.OpenAPIDef{
|
||||
ID: "GetChannelByID",
|
||||
Tags: []string{"channels"},
|
||||
Summary: "Get notification channel by ID",
|
||||
Description: "This endpoint returns a notification channel by ID",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(alertmanagertypes.Channel),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/channels", handler.New(provider.authZ.AdminAccess(provider.alertmanagerHandler.CreateChannel), handler.OpenAPIDef{
|
||||
ID: "CreateChannel",
|
||||
Tags: []string{"channels"},
|
||||
Summary: "Create notification channel",
|
||||
Description: "This endpoint creates a notification channel",
|
||||
Request: new(alertmanagertypes.Receiver),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(alertmanagertypes.Channel),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/channels/{id}", handler.New(provider.authZ.AdminAccess(provider.alertmanagerHandler.UpdateChannelByID), handler.OpenAPIDef{
|
||||
ID: "UpdateChannelByID",
|
||||
Tags: []string{"channels"},
|
||||
Summary: "Update notification channel",
|
||||
Description: "This endpoint updates a notification channel by ID",
|
||||
Request: new(alertmanagertypes.Receiver),
|
||||
RequestContentType: "application/json",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/channels/{id}", handler.New(provider.authZ.AdminAccess(provider.alertmanagerHandler.DeleteChannelByID), handler.OpenAPIDef{
|
||||
ID: "DeleteChannelByID",
|
||||
Tags: []string{"channels"},
|
||||
Summary: "Delete notification channel",
|
||||
Description: "This endpoint deletes a notification channel by ID",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/channels/test", handler.New(provider.authZ.EditAccess(provider.alertmanagerHandler.TestReceiver), handler.OpenAPIDef{
|
||||
ID: "TestChannel",
|
||||
Tags: []string{"channels"},
|
||||
Summary: "Test notification channel",
|
||||
Description: "This endpoint tests a notification channel by sending a test notification",
|
||||
Request: new(alertmanagertypes.Receiver),
|
||||
RequestContentType: "application/json",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleEditor),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/testChannel", handler.New(provider.authZ.EditAccess(provider.alertmanagerHandler.TestReceiver), handler.OpenAPIDef{
|
||||
ID: "TestChannelDeprecated",
|
||||
Tags: []string{"channels"},
|
||||
Summary: "Test notification channel (deprecated)",
|
||||
Description: "Deprecated: use /api/v1/channels/test instead",
|
||||
Request: new(alertmanagertypes.Receiver),
|
||||
RequestContentType: "application/json",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
Deprecated: true,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleEditor),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/route_policies", handler.New(provider.authZ.ViewAccess(provider.alertmanagerHandler.GetAllRoutePolicies), handler.OpenAPIDef{
|
||||
ID: "GetAllRoutePolicies",
|
||||
Tags: []string{"routepolicies"},
|
||||
Summary: "List route policies",
|
||||
Description: "This endpoint lists all route policies for the organization",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: make([]*alertmanagertypes.GettableRoutePolicy, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/route_policies/{id}", handler.New(provider.authZ.ViewAccess(provider.alertmanagerHandler.GetRoutePolicyByID), handler.OpenAPIDef{
|
||||
ID: "GetRoutePolicyByID",
|
||||
Tags: []string{"routepolicies"},
|
||||
Summary: "Get route policy by ID",
|
||||
Description: "This endpoint returns a route policy by ID",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(alertmanagertypes.GettableRoutePolicy),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/route_policies", handler.New(provider.authZ.AdminAccess(provider.alertmanagerHandler.CreateRoutePolicy), handler.OpenAPIDef{
|
||||
ID: "CreateRoutePolicy",
|
||||
Tags: []string{"routepolicies"},
|
||||
Summary: "Create route policy",
|
||||
Description: "This endpoint creates a route policy",
|
||||
Request: new(alertmanagertypes.PostableRoutePolicy),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(alertmanagertypes.GettableRoutePolicy),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/route_policies/{id}", handler.New(provider.authZ.AdminAccess(provider.alertmanagerHandler.UpdateRoutePolicy), handler.OpenAPIDef{
|
||||
ID: "UpdateRoutePolicy",
|
||||
Tags: []string{"routepolicies"},
|
||||
Summary: "Update route policy",
|
||||
Description: "This endpoint updates a route policy by ID",
|
||||
Request: new(alertmanagertypes.PostableRoutePolicy),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(alertmanagertypes.GettableRoutePolicy),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/route_policies/{id}", handler.New(provider.authZ.AdminAccess(provider.alertmanagerHandler.DeleteRoutePolicyByID), handler.OpenAPIDef{
|
||||
ID: "DeleteRoutePolicyByID",
|
||||
Tags: []string{"routepolicies"},
|
||||
Summary: "Delete route policy",
|
||||
Description: "This endpoint deletes a route policy by ID",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/alerts", handler.New(provider.authZ.ViewAccess(provider.alertmanagerHandler.GetAlerts), handler.OpenAPIDef{
|
||||
ID: "GetAlerts",
|
||||
Tags: []string{"alerts"},
|
||||
Summary: "Get alerts",
|
||||
Description: "This endpoint returns alerts for the organization",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: make(alertmanagertypes.DeprecatedGettableAlerts, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package signozapiserver
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
"github.com/SigNoz/signoz/pkg/apiserver"
|
||||
"github.com/SigNoz/signoz/pkg/authz"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
@@ -58,7 +57,6 @@ type provider struct {
|
||||
factoryHandler factory.Handler
|
||||
cloudIntegrationHandler cloudintegration.Handler
|
||||
ruleStateHistoryHandler rulestatehistory.Handler
|
||||
alertmanagerHandler alertmanager.Handler
|
||||
}
|
||||
|
||||
func NewFactory(
|
||||
@@ -85,7 +83,6 @@ func NewFactory(
|
||||
factoryHandler factory.Handler,
|
||||
cloudIntegrationHandler cloudintegration.Handler,
|
||||
ruleStateHistoryHandler rulestatehistory.Handler,
|
||||
alertmanagerHandler alertmanager.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(
|
||||
@@ -115,7 +112,6 @@ func NewFactory(
|
||||
factoryHandler,
|
||||
cloudIntegrationHandler,
|
||||
ruleStateHistoryHandler,
|
||||
alertmanagerHandler,
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -147,7 +143,6 @@ func newProvider(
|
||||
factoryHandler factory.Handler,
|
||||
cloudIntegrationHandler cloudintegration.Handler,
|
||||
ruleStateHistoryHandler rulestatehistory.Handler,
|
||||
alertmanagerHandler alertmanager.Handler,
|
||||
) (apiserver.APIServer, error) {
|
||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/apiserver/signozapiserver")
|
||||
router := mux.NewRouter().UseEncodedPath()
|
||||
@@ -177,7 +172,6 @@ func newProvider(
|
||||
factoryHandler: factoryHandler,
|
||||
cloudIntegrationHandler: cloudIntegrationHandler,
|
||||
ruleStateHistoryHandler: ruleStateHistoryHandler,
|
||||
alertmanagerHandler: alertmanagerHandler,
|
||||
}
|
||||
|
||||
provider.authZ = middleware.NewAuthZ(settings.Logger(), orgGetter, authz)
|
||||
@@ -278,10 +272,6 @@ func (provider *provider) AddToRouter(router *mux.Router) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := provider.addAlertmanagerRoutes(router); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ func newConfig() factory.Config {
|
||||
Agent: AgentConfig{
|
||||
// we will maintain the latest version of cloud integration agent from here,
|
||||
// till we automate it externally or figure out a way to validate it.
|
||||
Version: "v0.0.9",
|
||||
Version: "v0.0.8",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
|
||||
"github.com/prometheus/prometheus/promql"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
errorsV2 "github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/http/middleware"
|
||||
"github.com/SigNoz/signoz/pkg/http/render"
|
||||
@@ -139,6 +140,8 @@ type APIHandler struct {
|
||||
|
||||
pvcsRepo *inframetrics.PvcsRepo
|
||||
|
||||
AlertmanagerAPI *alertmanager.API
|
||||
|
||||
LicensingAPI licensing.API
|
||||
|
||||
QueryParserAPI *queryparser.API
|
||||
@@ -165,6 +168,8 @@ type APIHandlerOpts struct {
|
||||
// Flux Interval
|
||||
FluxInterval time.Duration
|
||||
|
||||
AlertmanagerAPI *alertmanager.API
|
||||
|
||||
LicensingAPI licensing.API
|
||||
|
||||
QueryParserAPI *queryparser.API
|
||||
@@ -225,6 +230,7 @@ func NewAPIHandler(opts APIHandlerOpts, config signoz.Config) (*APIHandler, erro
|
||||
statefulsetsRepo: statefulsetsRepo,
|
||||
jobsRepo: jobsRepo,
|
||||
pvcsRepo: pvcsRepo,
|
||||
AlertmanagerAPI: opts.AlertmanagerAPI,
|
||||
LicensingAPI: opts.LicensingAPI,
|
||||
Signoz: opts.Signoz,
|
||||
QueryParserAPI: opts.QueryParserAPI,
|
||||
@@ -496,6 +502,21 @@ func (aH *APIHandler) Respond(w http.ResponseWriter, data interface{}) {
|
||||
func (aH *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) {
|
||||
router.HandleFunc("/api/v1/query_range", am.ViewAccess(aH.queryRangeMetrics)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/query", am.ViewAccess(aH.queryMetrics)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/channels", am.ViewAccess(aH.AlertmanagerAPI.ListChannels)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/channels/{id}", am.ViewAccess(aH.AlertmanagerAPI.GetChannelByID)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/channels/{id}", am.AdminAccess(aH.AlertmanagerAPI.UpdateChannelByID)).Methods(http.MethodPut)
|
||||
router.HandleFunc("/api/v1/channels/{id}", am.AdminAccess(aH.AlertmanagerAPI.DeleteChannelByID)).Methods(http.MethodDelete)
|
||||
router.HandleFunc("/api/v1/channels", am.EditAccess(aH.AlertmanagerAPI.CreateChannel)).Methods(http.MethodPost)
|
||||
router.HandleFunc("/api/v1/testChannel", am.EditAccess(aH.AlertmanagerAPI.TestReceiver)).Methods(http.MethodPost)
|
||||
|
||||
router.HandleFunc("/api/v1/route_policies", am.ViewAccess(aH.AlertmanagerAPI.GetAllRoutePolicies)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/route_policies/{id}", am.ViewAccess(aH.AlertmanagerAPI.GetRoutePolicyByID)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/route_policies", am.AdminAccess(aH.AlertmanagerAPI.CreateRoutePolicy)).Methods(http.MethodPost)
|
||||
router.HandleFunc("/api/v1/route_policies/{id}", am.AdminAccess(aH.AlertmanagerAPI.DeleteRoutePolicyByID)).Methods(http.MethodDelete)
|
||||
router.HandleFunc("/api/v1/route_policies/{id}", am.AdminAccess(aH.AlertmanagerAPI.UpdateRoutePolicy)).Methods(http.MethodPut)
|
||||
|
||||
router.HandleFunc("/api/v1/alerts", am.ViewAccess(aH.AlertmanagerAPI.GetAlerts)).Methods(http.MethodGet)
|
||||
|
||||
router.HandleFunc("/api/v1/rules", am.ViewAccess(aH.listRules)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/rules/{id}", am.ViewAccess(aH.getRule)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/rules", am.EditAccess(aH.createRule)).Methods(http.MethodPost)
|
||||
|
||||
@@ -136,6 +136,7 @@ func NewServer(config signoz.Config, signoz *signoz.SigNoz) (*Server, error) {
|
||||
CloudIntegrationsController: cloudIntegrationsController,
|
||||
LogsParsingPipelineController: logParsingPipelineController,
|
||||
FluxInterval: config.Querier.FluxInterval,
|
||||
AlertmanagerAPI: alertmanager.NewAPI(signoz.Alertmanager),
|
||||
LicensingAPI: nooplicensing.NewLicenseAPI(),
|
||||
Signoz: signoz,
|
||||
QueryParserAPI: queryparser.NewAPI(signoz.Instrumentation.ToProviderSettings(), signoz.QueryParser),
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package signoz
|
||||
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
||||
"github.com/SigNoz/signoz/pkg/analytics"
|
||||
"github.com/SigNoz/signoz/pkg/authz"
|
||||
"github.com/SigNoz/signoz/pkg/authz/signozauthzapi"
|
||||
@@ -64,7 +62,6 @@ type Handlers struct {
|
||||
RegistryHandler factory.Handler
|
||||
CloudIntegrationHandler cloudintegration.Handler
|
||||
RuleStateHistory rulestatehistory.Handler
|
||||
AlertmanagerHandler alertmanager.Handler
|
||||
}
|
||||
|
||||
func NewHandlers(
|
||||
@@ -80,7 +77,6 @@ func NewHandlers(
|
||||
authz authz.AuthZ,
|
||||
zeusService zeus.Zeus,
|
||||
registryHandler factory.Handler,
|
||||
alertmanagerService alertmanager.Alertmanager,
|
||||
) Handlers {
|
||||
return Handlers{
|
||||
SavedView: implsavedview.NewHandler(modules.SavedView),
|
||||
@@ -103,6 +99,5 @@ func NewHandlers(
|
||||
RegistryHandler: registryHandler,
|
||||
RuleStateHistory: implrulestatehistory.NewHandler(modules.RuleStateHistory),
|
||||
CloudIntegrationHandler: implcloudintegration.NewHandler(modules.CloudIntegration),
|
||||
AlertmanagerHandler: signozalertmanager.NewHandler(alertmanagerService),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func TestNewHandlers(t *testing.T) {
|
||||
|
||||
querierHandler := querier.NewHandler(providerSettings, nil, nil)
|
||||
registryHandler := factory.NewHandler(nil)
|
||||
handlers := NewHandlers(modules, providerSettings, nil, querierHandler, nil, nil, nil, nil, nil, nil, nil, registryHandler, alertmanager)
|
||||
handlers := NewHandlers(modules, providerSettings, nil, querierHandler, nil, nil, nil, nil, nil, nil, nil, registryHandler)
|
||||
reflectVal := reflect.ValueOf(handlers)
|
||||
for i := 0; i < reflectVal.NumField(); i++ {
|
||||
f := reflectVal.Field(i)
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
"github.com/SigNoz/signoz/pkg/apiserver"
|
||||
"github.com/SigNoz/signoz/pkg/apiserver/signozapiserver"
|
||||
"github.com/SigNoz/signoz/pkg/authz"
|
||||
@@ -70,7 +69,6 @@ func NewOpenAPI(ctx context.Context, instrumentation instrumentation.Instrumenta
|
||||
struct{ factory.Handler }{},
|
||||
struct{ cloudintegration.Handler }{},
|
||||
struct{ rulestatehistory.Handler }{},
|
||||
struct{ alertmanager.Handler }{},
|
||||
).New(ctx, instrumentation.ToProviderSettings(), apiserver.Config{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -288,7 +288,6 @@ func NewAPIServerProviderFactories(orgGetter organization.Getter, authz authz.Au
|
||||
handlers.RegistryHandler,
|
||||
handlers.CloudIntegrationHandler,
|
||||
handlers.RuleStateHistory,
|
||||
handlers.AlertmanagerHandler,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ func New(
|
||||
|
||||
// Initialize all handlers for the modules
|
||||
registryHandler := factory.NewHandler(registry)
|
||||
handlers := NewHandlers(modules, providerSettings, analytics, querierHandler, licensing, global, flagger, gateway, telemetryMetadataStore, authz, zeus, registryHandler, alertmanager)
|
||||
handlers := NewHandlers(modules, providerSettings, analytics, querierHandler, licensing, global, flagger, gateway, telemetryMetadataStore, authz, zeus, registryHandler)
|
||||
|
||||
// Initialize the API server (after registry so it can access service health)
|
||||
apiserverInstance, err := factory.NewProviderFromNamedMap(
|
||||
|
||||
@@ -889,12 +889,7 @@ func (t *telemetryMetaStore) getMetricsKeys(ctx context.Context, fieldKeySelecto
|
||||
// }
|
||||
|
||||
if fieldKeySelector.MetricContext != nil {
|
||||
if fieldKeySelector.MetricContext.MetricName != "" {
|
||||
fieldConds = append(fieldConds, sb.E("metric_name", fieldKeySelector.MetricContext.MetricName))
|
||||
}
|
||||
if fieldKeySelector.MetricContext.MetricNamespace != "" {
|
||||
fieldConds = append(fieldConds, sb.Like("metric_name", escapeForLike(fieldKeySelector.MetricContext.MetricNamespace)+"%"))
|
||||
}
|
||||
fieldConds = append(fieldConds, sb.E("metric_name", fieldKeySelector.MetricContext.MetricName))
|
||||
}
|
||||
|
||||
conds = append(conds, sb.And(fieldConds...))
|
||||
@@ -982,12 +977,7 @@ func (t *telemetryMetaStore) getMeterSourceMetricKeys(ctx context.Context, field
|
||||
fieldConds = append(fieldConds, sb.NotLike("attr_name", "\\_\\_%"))
|
||||
|
||||
if fieldKeySelector.MetricContext != nil {
|
||||
if fieldKeySelector.MetricContext.MetricName != "" {
|
||||
fieldConds = append(fieldConds, sb.E("metric_name", fieldKeySelector.MetricContext.MetricName))
|
||||
}
|
||||
if fieldKeySelector.MetricContext.MetricNamespace != "" {
|
||||
fieldConds = append(fieldConds, sb.Like("metric_name", escapeForLike(fieldKeySelector.MetricContext.MetricNamespace)+"%"))
|
||||
}
|
||||
fieldConds = append(fieldConds, sb.E("metric_name", fieldKeySelector.MetricContext.MetricName))
|
||||
}
|
||||
|
||||
conds = append(conds, sb.And(fieldConds...))
|
||||
@@ -1081,8 +1071,8 @@ func enrichWithIntrinsicMetricKeys(keys map[string][]*telemetrytypes.TelemetryFi
|
||||
if selector.Signal != telemetrytypes.SignalMetrics && selector.Signal != telemetrytypes.SignalUnspecified {
|
||||
continue
|
||||
}
|
||||
// If metric filters are provided, do not surface intrinsic metric keys.
|
||||
if selector.MetricContext != nil && (selector.MetricContext.MetricName != "" || selector.MetricContext.MetricNamespace != "") {
|
||||
// If a metricName is provided, don’t surface intrinsic metric keys
|
||||
if selector.MetricContext != nil && selector.MetricContext.MetricName != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1738,12 +1728,9 @@ func (t *telemetryMetaStore) getMetricFieldValues(ctx context.Context, fieldValu
|
||||
sb.Where(sb.E("attr_datatype", fieldValueSelector.FieldDataType.TagDataType()))
|
||||
}
|
||||
|
||||
if fieldValueSelector.MetricContext != nil && fieldValueSelector.MetricContext.MetricName != "" {
|
||||
if fieldValueSelector.MetricContext != nil {
|
||||
sb.Where(sb.E("metric_name", fieldValueSelector.MetricContext.MetricName))
|
||||
}
|
||||
if fieldValueSelector.MetricContext != nil && fieldValueSelector.MetricContext.MetricNamespace != "" {
|
||||
sb.Where(sb.Like("metric_name", escapeForLike(fieldValueSelector.MetricContext.MetricNamespace)+"%"))
|
||||
}
|
||||
|
||||
if fieldValueSelector.StartUnixMilli > 0 {
|
||||
sb.Where(sb.GE("last_reported_unix_milli", fieldValueSelector.StartUnixMilli))
|
||||
@@ -1825,9 +1812,6 @@ func (t *telemetryMetaStore) getIntrinsicMetricFieldValues(ctx context.Context,
|
||||
if fieldValueSelector.MetricContext != nil && fieldValueSelector.MetricContext.MetricName != "" {
|
||||
sb.Where(sb.E("metric_name", fieldValueSelector.MetricContext.MetricName))
|
||||
}
|
||||
if fieldValueSelector.MetricContext != nil && fieldValueSelector.MetricContext.MetricNamespace != "" {
|
||||
sb.Where(sb.Like("metric_name", escapeForLike(fieldValueSelector.MetricContext.MetricNamespace)+"%"))
|
||||
}
|
||||
|
||||
if fieldValueSelector.StartUnixMilli > 0 {
|
||||
sb.Where(sb.GE("unix_milli", fieldValueSelector.StartUnixMilli))
|
||||
@@ -1885,13 +1869,6 @@ func (t *telemetryMetaStore) getMeterSourceMetricFieldValues(ctx context.Context
|
||||
}
|
||||
sb.Where(sb.NotLike("attr.1", "\\_\\_%"))
|
||||
|
||||
if fieldValueSelector.MetricContext != nil && fieldValueSelector.MetricContext.MetricName != "" {
|
||||
sb.Where(sb.E("metric_name", fieldValueSelector.MetricContext.MetricName))
|
||||
}
|
||||
if fieldValueSelector.MetricContext != nil && fieldValueSelector.MetricContext.MetricNamespace != "" {
|
||||
sb.Where(sb.Like("metric_name", escapeForLike(fieldValueSelector.MetricContext.MetricNamespace)+"%"))
|
||||
}
|
||||
|
||||
if fieldValueSelector.Value != "" {
|
||||
if fieldValueSelector.SelectorMatchType == telemetrytypes.FieldSelectorMatchTypeExact {
|
||||
sb.Where(sb.E("attr.2", fieldValueSelector.Value))
|
||||
|
||||
@@ -320,20 +320,6 @@ func TestEnrichWithIntrinsicMetricKeys(t *testing.T) {
|
||||
},
|
||||
)
|
||||
assert.NotContains(t, result, "metric_name")
|
||||
|
||||
result = enrichWithIntrinsicMetricKeys(
|
||||
map[string][]*telemetrytypes.TelemetryFieldKey{},
|
||||
[]*telemetrytypes.FieldKeySelector{
|
||||
{
|
||||
Signal: telemetrytypes.SignalMetrics,
|
||||
MetricContext: &telemetrytypes.MetricContext{
|
||||
MetricNamespace: "system.cpu",
|
||||
},
|
||||
SelectorMatchType: telemetrytypes.FieldSelectorMatchTypeFuzzy,
|
||||
},
|
||||
},
|
||||
)
|
||||
assert.NotContains(t, result, "metric_name")
|
||||
}
|
||||
|
||||
func TestGetMetricFieldValuesIntrinsicMetricName(t *testing.T) {
|
||||
@@ -406,174 +392,3 @@ func TestGetMetricFieldValuesIntrinsicBoolReturnsEmpty(t *testing.T) {
|
||||
assert.Empty(t, values.BoolValues)
|
||||
require.NoError(t, mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
func TestGetMetricFieldValuesAppliesMetricNamespace(t *testing.T) {
|
||||
mockTelemetryStore := telemetrystoretest.New(telemetrystore.Config{}, ®exMatcher{})
|
||||
mock := mockTelemetryStore.Mock()
|
||||
|
||||
metadata := newTestTelemetryMetaStoreTestHelper(mockTelemetryStore)
|
||||
|
||||
valueRows := cmock.NewRows([]cmock.ColumnType{
|
||||
{Name: "attr_string_value", Type: "String"},
|
||||
}, [][]any{{"value.a"}})
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta("SELECT DISTINCT attr_string_value FROM signoz_metrics.distributed_metadata WHERE attr_name = ? AND metric_name LIKE ? LIMIT ?")).
|
||||
WithArgs("custom_key", "system.cpu%", 11).
|
||||
WillReturnRows(valueRows)
|
||||
|
||||
values, complete, err := metadata.(*telemetryMetaStore).getMetricFieldValues(context.Background(), &telemetrytypes.FieldValueSelector{
|
||||
FieldKeySelector: &telemetrytypes.FieldKeySelector{
|
||||
Signal: telemetrytypes.SignalMetrics,
|
||||
Name: "custom_key",
|
||||
Limit: 10,
|
||||
SelectorMatchType: telemetrytypes.FieldSelectorMatchTypeFuzzy,
|
||||
MetricContext: &telemetrytypes.MetricContext{
|
||||
MetricNamespace: "system.cpu",
|
||||
},
|
||||
},
|
||||
Limit: 10,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.True(t, complete)
|
||||
assert.ElementsMatch(t, []string{"value.a"}, values.StringValues)
|
||||
require.NoError(t, mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
func TestGetMetricFieldValuesIntrinsicMetricNameAppliesMetricNamespace(t *testing.T) {
|
||||
mockTelemetryStore := telemetrystoretest.New(telemetrystore.Config{}, ®exMatcher{})
|
||||
mock := mockTelemetryStore.Mock()
|
||||
|
||||
metadata := newTestTelemetryMetaStoreTestHelper(mockTelemetryStore)
|
||||
|
||||
valueRows := cmock.NewRows([]cmock.ColumnType{
|
||||
{Name: "metric_name", Type: "String"},
|
||||
}, [][]any{{"system.cpu.utilization"}})
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta("SELECT metric_name FROM signoz_metrics.distributed_time_series_v4_1week WHERE metric_name LIKE ? GROUP BY metric_name LIMIT ?")).
|
||||
WithArgs("system.cpu%", 51).
|
||||
WillReturnRows(valueRows)
|
||||
|
||||
metadataRows := cmock.NewRows([]cmock.ColumnType{
|
||||
{Name: "attr_string_value", Type: "String"},
|
||||
}, [][]any{})
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta("SELECT DISTINCT attr_string_value FROM signoz_metrics.distributed_metadata WHERE attr_name = ? AND metric_name LIKE ? LIMIT ?")).
|
||||
WithArgs("metric_name", "system.cpu%", 50).
|
||||
WillReturnRows(metadataRows)
|
||||
|
||||
values, complete, err := metadata.(*telemetryMetaStore).getMetricFieldValues(context.Background(), &telemetrytypes.FieldValueSelector{
|
||||
FieldKeySelector: &telemetrytypes.FieldKeySelector{
|
||||
Signal: telemetrytypes.SignalMetrics,
|
||||
Name: "metric_name",
|
||||
Limit: 50,
|
||||
SelectorMatchType: telemetrytypes.FieldSelectorMatchTypeFuzzy,
|
||||
MetricContext: &telemetrytypes.MetricContext{
|
||||
MetricNamespace: "system.cpu",
|
||||
},
|
||||
},
|
||||
Limit: 50,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.True(t, complete)
|
||||
assert.ElementsMatch(t, []string{"system.cpu.utilization"}, values.StringValues)
|
||||
require.NoError(t, mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
func TestGetMeterSourceMetricFieldValuesAppliesMetricNamespace(t *testing.T) {
|
||||
mockTelemetryStore := telemetrystoretest.New(telemetrystore.Config{}, ®exMatcher{})
|
||||
mock := mockTelemetryStore.Mock()
|
||||
|
||||
metadata := newTestTelemetryMetaStoreTestHelper(mockTelemetryStore)
|
||||
|
||||
rows := cmock.NewRows([]cmock.ColumnType{
|
||||
{Name: "attr", Type: "Array(String)"},
|
||||
}, [][]any{{[]string{"service.name", "frontend"}}})
|
||||
|
||||
mock.ExpectQuery(`SELECT .*distributed_samples_agg_1d.*metric_name LIKE .*`).
|
||||
WithArgs("service.name", "\\_\\_%", "system.cpu%", "", 11).
|
||||
WillReturnRows(rows)
|
||||
|
||||
values, complete, err := metadata.(*telemetryMetaStore).getMeterSourceMetricFieldValues(context.Background(), &telemetrytypes.FieldValueSelector{
|
||||
FieldKeySelector: &telemetrytypes.FieldKeySelector{
|
||||
Signal: telemetrytypes.SignalMetrics,
|
||||
Source: telemetrytypes.SourceMeter,
|
||||
Name: "service.name",
|
||||
MetricContext: &telemetrytypes.MetricContext{
|
||||
MetricNamespace: "system.cpu",
|
||||
},
|
||||
},
|
||||
Limit: 10,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.True(t, complete)
|
||||
assert.ElementsMatch(t, []string{"frontend"}, values.StringValues)
|
||||
require.NoError(t, mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
func TestGetMetricsKeysAppliesMetricNamespace(t *testing.T) {
|
||||
mockTelemetryStore := telemetrystoretest.New(telemetrystore.Config{}, ®exMatcher{})
|
||||
mock := mockTelemetryStore.Mock()
|
||||
|
||||
metadata := newTestTelemetryMetaStoreTestHelper(mockTelemetryStore)
|
||||
|
||||
rows := cmock.NewRows([]cmock.ColumnType{
|
||||
{Name: "name", Type: "String"},
|
||||
{Name: "field_context", Type: "String"},
|
||||
{Name: "field_data_type", Type: "String"},
|
||||
{Name: "priority", Type: "UInt8"},
|
||||
}, [][]any{{"service.name", "resource", "String", 1}})
|
||||
|
||||
mock.ExpectQuery(`(?s)SELECT.*distributed_metadata.*metric_name LIKE.*`).
|
||||
WithArgs("%service%", "\\_\\_%", "system.cpu%", 11).
|
||||
WillReturnRows(rows)
|
||||
|
||||
keys, complete, err := metadata.(*telemetryMetaStore).getMetricsKeys(context.Background(), []*telemetrytypes.FieldKeySelector{
|
||||
{
|
||||
Signal: telemetrytypes.SignalMetrics,
|
||||
Name: "service",
|
||||
Limit: 10,
|
||||
SelectorMatchType: telemetrytypes.FieldSelectorMatchTypeFuzzy,
|
||||
MetricContext: &telemetrytypes.MetricContext{
|
||||
MetricNamespace: "system.cpu",
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.True(t, complete)
|
||||
assert.Len(t, keys, 1)
|
||||
assert.Equal(t, "service.name", keys[0].Name)
|
||||
require.NoError(t, mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
func TestGetMeterSourceMetricKeysAppliesMetricNamespace(t *testing.T) {
|
||||
mockTelemetryStore := telemetrystoretest.New(telemetrystore.Config{}, ®exMatcher{})
|
||||
mock := mockTelemetryStore.Mock()
|
||||
|
||||
metadata := newTestTelemetryMetaStoreTestHelper(mockTelemetryStore)
|
||||
|
||||
rows := cmock.NewRows([]cmock.ColumnType{
|
||||
{Name: "attr_name", Type: "String"},
|
||||
}, [][]any{{"service.name"}})
|
||||
|
||||
mock.ExpectQuery(`SELECT.*distributed_samples_agg_1d.*metric_name LIKE.*`).
|
||||
WithArgs("%service%", "\\_\\_%", "system.cpu%", 10).
|
||||
WillReturnRows(rows)
|
||||
|
||||
keys, complete, err := metadata.(*telemetryMetaStore).getMeterSourceMetricKeys(context.Background(), []*telemetrytypes.FieldKeySelector{
|
||||
{
|
||||
Signal: telemetrytypes.SignalMetrics,
|
||||
Source: telemetrytypes.SourceMeter,
|
||||
Name: "service",
|
||||
Limit: 10,
|
||||
SelectorMatchType: telemetrytypes.FieldSelectorMatchTypeFuzzy,
|
||||
MetricContext: &telemetrytypes.MetricContext{
|
||||
MetricNamespace: "system.cpu",
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.True(t, complete)
|
||||
assert.Len(t, keys, 1)
|
||||
assert.Equal(t, "service.name", keys[0].Name)
|
||||
require.NoError(t, mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
@@ -34,10 +34,10 @@ type Channel struct {
|
||||
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
Name string `json:"name" required:"true" bun:"name"`
|
||||
Type string `json:"type" required:"true" bun:"type"`
|
||||
Data string `json:"data" required:"true" bun:"data"`
|
||||
OrgID string `json:"orgId" required:"true" bun:"org_id"`
|
||||
Name string `json:"name" bun:"name"`
|
||||
Type string `json:"type" bun:"type"`
|
||||
Data string `json:"data" bun:"data"`
|
||||
OrgID string `json:"org_id" bun:"org_id"`
|
||||
}
|
||||
|
||||
// NewChannelFromReceiver creates a new Channel from a Receiver.
|
||||
|
||||
@@ -12,12 +12,12 @@ import (
|
||||
)
|
||||
|
||||
type PostableRoutePolicy struct {
|
||||
Expression string `json:"expression" required:"true"`
|
||||
Expression string `json:"expression"`
|
||||
ExpressionKind ExpressionKind `json:"kind"`
|
||||
Channels []string `json:"channels" required:"true"`
|
||||
Name string `json:"name" required:"true"`
|
||||
Channels []string `json:"channels"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Tags []string `json:"tags,omitempty" nullable:"true"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
}
|
||||
|
||||
func (p *PostableRoutePolicy) Validate() error {
|
||||
@@ -53,13 +53,15 @@ func (p *PostableRoutePolicy) Validate() error {
|
||||
}
|
||||
|
||||
type GettableRoutePolicy struct {
|
||||
PostableRoutePolicy
|
||||
PostableRoutePolicy // Embedded
|
||||
|
||||
ID string `json:"id" required:"true"`
|
||||
CreatedAt time.Time `json:"createdAt" required:"true"`
|
||||
UpdatedAt time.Time `json:"updatedAt" required:"true"`
|
||||
CreatedBy *string `json:"createdBy" nullable:"true"`
|
||||
UpdatedBy *string `json:"updatedBy" nullable:"true"`
|
||||
ID string `json:"id"`
|
||||
|
||||
// Audit fields
|
||||
CreatedAt *time.Time `json:"createdAt"`
|
||||
UpdatedAt *time.Time `json:"updatedAt"`
|
||||
CreatedBy *string `json:"createdBy"`
|
||||
UpdatedBy *string `json:"updatedBy"`
|
||||
}
|
||||
|
||||
type ExpressionKind struct {
|
||||
@@ -71,13 +73,6 @@ var (
|
||||
PolicyBasedExpression = ExpressionKind{valuer.NewString("policy")}
|
||||
)
|
||||
|
||||
func (ExpressionKind) Enum() []any {
|
||||
return []any{
|
||||
RuleBasedExpression,
|
||||
PolicyBasedExpression,
|
||||
}
|
||||
}
|
||||
|
||||
// RoutePolicy represents the database model for expression routes.
|
||||
type RoutePolicy struct {
|
||||
bun.BaseModel `bun:"table:route_policy"`
|
||||
|
||||
@@ -268,8 +268,7 @@ func (t *TelemetryFieldValues) NumValues() int {
|
||||
}
|
||||
|
||||
type MetricContext struct {
|
||||
MetricName string `json:"metricName"`
|
||||
MetricNamespace string `json:"metricNamespace,omitempty"`
|
||||
MetricName string `json:"metricName"`
|
||||
}
|
||||
|
||||
type FieldKeySelector struct {
|
||||
@@ -298,16 +297,15 @@ type GettableFieldKeys struct {
|
||||
}
|
||||
|
||||
type PostableFieldKeysParams struct {
|
||||
Signal Signal `query:"signal"`
|
||||
Source Source `query:"source"`
|
||||
Limit int `query:"limit"`
|
||||
StartUnixMilli int64 `query:"startUnixMilli"`
|
||||
EndUnixMilli int64 `query:"endUnixMilli"`
|
||||
FieldContext FieldContext `query:"fieldContext"`
|
||||
FieldDataType FieldDataType `query:"fieldDataType"`
|
||||
MetricName string `query:"metricName"`
|
||||
MetricNamespace string `query:"metricNamespace"`
|
||||
SearchText string `query:"searchText"`
|
||||
Signal Signal `query:"signal"`
|
||||
Source Source `query:"source"`
|
||||
Limit int `query:"limit"`
|
||||
StartUnixMilli int64 `query:"startUnixMilli"`
|
||||
EndUnixMilli int64 `query:"endUnixMilli"`
|
||||
FieldContext FieldContext `query:"fieldContext"`
|
||||
FieldDataType FieldDataType `query:"fieldDataType"`
|
||||
MetricName string `query:"metricName"`
|
||||
SearchText string `query:"searchText"`
|
||||
}
|
||||
|
||||
type GettableFieldValues struct {
|
||||
@@ -346,10 +344,9 @@ func NewFieldKeySelectorFromPostableFieldKeysParams(params PostableFieldKeysPara
|
||||
req.Limit = 1000
|
||||
}
|
||||
|
||||
if params.MetricName != "" || params.MetricNamespace != "" {
|
||||
if params.MetricName != "" {
|
||||
req.MetricContext = &MetricContext{
|
||||
MetricName: params.MetricName,
|
||||
MetricNamespace: params.MetricNamespace,
|
||||
MetricName: params.MetricName,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -394,20 +394,3 @@ func TestNormalize(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFieldKeySelectorFromPostableFieldKeysParamsMetricNamespace(t *testing.T) {
|
||||
selector := NewFieldKeySelectorFromPostableFieldKeysParams(PostableFieldKeysParams{
|
||||
Signal: SignalMetrics,
|
||||
MetricNamespace: "system.cpu",
|
||||
})
|
||||
|
||||
if selector.MetricContext == nil {
|
||||
t.Fatalf("expected metric context to be set")
|
||||
}
|
||||
if selector.MetricContext.MetricNamespace != "system.cpu" {
|
||||
t.Fatalf("expected metric namespace to be propagated, got %q", selector.MetricContext.MetricNamespace)
|
||||
}
|
||||
if selector.MetricContext.MetricName != "" {
|
||||
t.Fatalf("expected metric name to remain empty, got %q", selector.MetricContext.MetricName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,211 +658,3 @@ def test_non_existent_metrics_returns_404(
|
||||
get_error_message(response.json())
|
||||
== "could not find the metric whatevergoennnsgoeshere"
|
||||
)
|
||||
|
||||
|
||||
# Verify /api/v1/fields/values filters label values by metricNamespace prefix.
|
||||
# Inserts metrics under ns.a and ns.b, then asserts a specific prefix returns
|
||||
# only matching values while a common prefix returns both.
|
||||
def test_metric_namespace_values_filtering(
|
||||
signoz: types.SigNoz,
|
||||
create_user_admin: None, # pylint: disable=unused-argument
|
||||
get_token: Callable[[str, str], str],
|
||||
insert_metrics: Callable[[List[Metrics]], None],
|
||||
) -> None:
|
||||
now = datetime.now(tz=timezone.utc).replace(second=0, microsecond=0)
|
||||
|
||||
metrics: List[Metrics] = [
|
||||
Metrics(
|
||||
metric_name="ns.a.requests_total",
|
||||
labels={"service": "svc-a"},
|
||||
timestamp=now - timedelta(minutes=2),
|
||||
value=10.0,
|
||||
),
|
||||
Metrics(
|
||||
metric_name="ns.b.requests_total",
|
||||
labels={"service": "svc-b"},
|
||||
timestamp=now - timedelta(minutes=2),
|
||||
value=20.0,
|
||||
),
|
||||
]
|
||||
insert_metrics(metrics)
|
||||
|
||||
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
|
||||
|
||||
# Specific prefix: metricNamespace=ns.a should return only svc-a
|
||||
response = requests.get(
|
||||
signoz.self.host_configs["8080"].get("/api/v1/fields/values"),
|
||||
timeout=5,
|
||||
headers={"authorization": f"Bearer {token}"},
|
||||
params={
|
||||
"signal": "metrics",
|
||||
"name": "service",
|
||||
"searchText": "",
|
||||
"metricNamespace": "ns.a",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
|
||||
values = response.json()["data"]["values"]["stringValues"]
|
||||
assert "svc-a" in values
|
||||
assert "svc-b" not in values
|
||||
|
||||
# Common prefix: metricNamespace=ns should return both
|
||||
response = requests.get(
|
||||
signoz.self.host_configs["8080"].get("/api/v1/fields/values"),
|
||||
timeout=5,
|
||||
headers={"authorization": f"Bearer {token}"},
|
||||
params={
|
||||
"signal": "metrics",
|
||||
"name": "service",
|
||||
"searchText": "",
|
||||
"metricNamespace": "ns",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
|
||||
values = response.json()["data"]["values"]["stringValues"]
|
||||
assert "svc-a" in values
|
||||
assert "svc-b" in values
|
||||
|
||||
|
||||
# Verify /api/v1/fields/values with name=metric_name filters metric names by
|
||||
# metricNamespace prefix. A specific prefix returns only its metric names;
|
||||
# a common prefix returns metric names from all matching namespaces.
|
||||
def test_metric_namespace_metric_name_values_filtering(
|
||||
signoz: types.SigNoz,
|
||||
create_user_admin: None, # pylint: disable=unused-argument
|
||||
get_token: Callable[[str, str], str],
|
||||
insert_metrics: Callable[[List[Metrics]], None],
|
||||
) -> None:
|
||||
now = datetime.now(tz=timezone.utc).replace(second=0, microsecond=0)
|
||||
|
||||
metrics: List[Metrics] = [
|
||||
Metrics(
|
||||
metric_name="ns.a.cpu.utilization",
|
||||
labels={"host": "host-a"},
|
||||
timestamp=now - timedelta(minutes=2),
|
||||
value=50.0,
|
||||
),
|
||||
Metrics(
|
||||
metric_name="ns.b.cpu.utilization",
|
||||
labels={"host": "host-b"},
|
||||
timestamp=now - timedelta(minutes=2),
|
||||
value=60.0,
|
||||
),
|
||||
]
|
||||
insert_metrics(metrics)
|
||||
|
||||
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
|
||||
|
||||
# Specific prefix: metricNamespace=ns.a should return only ns.a.* metric names
|
||||
response = requests.get(
|
||||
signoz.self.host_configs["8080"].get("/api/v1/fields/values"),
|
||||
timeout=5,
|
||||
headers={"authorization": f"Bearer {token}"},
|
||||
params={
|
||||
"signal": "metrics",
|
||||
"name": "metric_name",
|
||||
"searchText": "",
|
||||
"metricNamespace": "ns.a",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
|
||||
values = response.json()["data"]["values"]["stringValues"]
|
||||
assert "ns.a.cpu.utilization" in values
|
||||
assert "ns.b.cpu.utilization" not in values
|
||||
|
||||
# Common prefix: metricNamespace=ns should return both
|
||||
response = requests.get(
|
||||
signoz.self.host_configs["8080"].get("/api/v1/fields/values"),
|
||||
timeout=5,
|
||||
headers={"authorization": f"Bearer {token}"},
|
||||
params={
|
||||
"signal": "metrics",
|
||||
"name": "metric_name",
|
||||
"searchText": "",
|
||||
"metricNamespace": "ns",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
|
||||
values = response.json()["data"]["values"]["stringValues"]
|
||||
assert "ns.a.cpu.utilization" in values
|
||||
assert "ns.b.cpu.utilization" in values
|
||||
|
||||
|
||||
# Verify /api/v1/fields/keys filters attribute keys by metricNamespace prefix.
|
||||
# Metrics under ns.a and ns.b carry distinct labels; a specific prefix returns
|
||||
# only its keys while a common prefix returns keys from both namespaces.
|
||||
def test_metric_namespace_keys_filtering(
|
||||
signoz: types.SigNoz,
|
||||
create_user_admin: None, # pylint: disable=unused-argument
|
||||
get_token: Callable[[str, str], str],
|
||||
insert_metrics: Callable[[List[Metrics]], None],
|
||||
) -> None:
|
||||
now = datetime.now(tz=timezone.utc).replace(second=0, microsecond=0)
|
||||
|
||||
metrics: List[Metrics] = [
|
||||
Metrics(
|
||||
metric_name="ns.a.cpu.utilization",
|
||||
labels={"a_only_label": "val-a"},
|
||||
timestamp=now - timedelta(minutes=2),
|
||||
value=10.0,
|
||||
),
|
||||
Metrics(
|
||||
metric_name="ns.b.cpu.utilization",
|
||||
labels={"b_only_label": "val-b"},
|
||||
timestamp=now - timedelta(minutes=2),
|
||||
value=20.0,
|
||||
),
|
||||
]
|
||||
insert_metrics(metrics)
|
||||
|
||||
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
|
||||
|
||||
# Specific prefix: metricNamespace=ns.a should return only a_only_label
|
||||
response = requests.get(
|
||||
signoz.self.host_configs["8080"].get("/api/v1/fields/keys"),
|
||||
timeout=5,
|
||||
headers={"authorization": f"Bearer {token}"},
|
||||
params={
|
||||
"signal": "metrics",
|
||||
"searchText": "label",
|
||||
"metricNamespace": "ns.a",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
|
||||
keys = response.json()["data"]["keys"]
|
||||
assert "a_only_label" in keys
|
||||
assert "b_only_label" not in keys
|
||||
|
||||
# Common prefix: metricNamespace=ns should return both keys
|
||||
response = requests.get(
|
||||
signoz.self.host_configs["8080"].get("/api/v1/fields/keys"),
|
||||
timeout=5,
|
||||
headers={"authorization": f"Bearer {token}"},
|
||||
params={
|
||||
"signal": "metrics",
|
||||
"searchText": "label",
|
||||
"metricNamespace": "ns",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
|
||||
keys = response.json()["data"]["keys"]
|
||||
assert "a_only_label" in keys
|
||||
assert "b_only_label" in keys
|
||||
|
||||
@@ -108,81 +108,3 @@ def test_list_meter_metric_names(
|
||||
assert (
|
||||
metric_name in metric_names
|
||||
), f"Expected {metric_name} in metric names, got: {metric_names}"
|
||||
|
||||
|
||||
# Verify /api/v1/fields/values with source=meter filters label values by metricNamespace
|
||||
# prefix. Inserts meter-source metrics under ns.a and ns.b, then asserts a specific
|
||||
# prefix returns only matching values while a common prefix returns both.
|
||||
def test_metric_namespace_meter_values_filtering(
|
||||
signoz: types.SigNoz,
|
||||
create_user_admin: None, # pylint: disable=unused-argument
|
||||
get_token: Callable[[str, str], str],
|
||||
insert_meter_samples: Callable[[List[MeterSample]], None],
|
||||
) -> None:
|
||||
now = datetime.now(tz=timezone.utc).replace(second=0, microsecond=0)
|
||||
|
||||
samples_a = make_meter_samples(
|
||||
"meter.ns.a.cost",
|
||||
{"service": "billing-a"},
|
||||
now,
|
||||
count=5,
|
||||
base_value=10.0,
|
||||
temporality="Delta",
|
||||
type_="Sum",
|
||||
is_monotonic=True,
|
||||
)
|
||||
samples_b = make_meter_samples(
|
||||
"meter.ns.b.cost",
|
||||
{"service": "billing-b"},
|
||||
now,
|
||||
count=5,
|
||||
base_value=20.0,
|
||||
temporality="Delta",
|
||||
type_="Sum",
|
||||
is_monotonic=True,
|
||||
)
|
||||
insert_meter_samples(samples_a + samples_b)
|
||||
|
||||
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
|
||||
|
||||
# Specific prefix: metricNamespace=meter.ns.a should return only billing-a
|
||||
response = requests.get(
|
||||
signoz.self.host_configs["8080"].get("/api/v1/fields/values"),
|
||||
timeout=5,
|
||||
headers={"authorization": f"Bearer {token}"},
|
||||
params={
|
||||
"signal": "metrics",
|
||||
"source": "meter",
|
||||
"name": "service",
|
||||
"searchText": "",
|
||||
"metricNamespace": "meter.ns.a",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
|
||||
values = response.json()["data"]["values"]["stringValues"]
|
||||
assert "billing-a" in values
|
||||
assert "billing-b" not in values
|
||||
|
||||
# Common prefix: metricNamespace=meter.ns should return both
|
||||
response = requests.get(
|
||||
signoz.self.host_configs["8080"].get("/api/v1/fields/values"),
|
||||
timeout=5,
|
||||
headers={"authorization": f"Bearer {token}"},
|
||||
params={
|
||||
"signal": "metrics",
|
||||
"source": "meter",
|
||||
"name": "service",
|
||||
"searchText": "",
|
||||
"metricNamespace": "meter.ns",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
|
||||
values = response.json()["data"]["values"]["stringValues"]
|
||||
assert "billing-a" in values
|
||||
assert "billing-b" in values
|
||||
|
||||
Reference in New Issue
Block a user