mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-30 05:40:33 +01:00
Compare commits
5 Commits
refactor/c
...
custom-rec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cab33095e | ||
|
|
78d0c65736 | ||
|
|
3ea759a4b3 | ||
|
|
081fdd318b | ||
|
|
d99ac9c9d7 |
@@ -96,6 +96,19 @@ components:
|
||||
- createdAt
|
||||
- updatedAt
|
||||
type: object
|
||||
AlertmanagertypesGoogleChatReceiverConfig:
|
||||
properties:
|
||||
http_config:
|
||||
$ref: '#/components/schemas/ConfigHTTPClientConfig'
|
||||
send_resolved:
|
||||
type: boolean
|
||||
text:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
webhook_url:
|
||||
$ref: '#/components/schemas/ConfigSecretURL'
|
||||
type: object
|
||||
AlertmanagertypesMaintenanceKind:
|
||||
enum:
|
||||
- fixed
|
||||
@@ -147,6 +160,8 @@ components:
|
||||
type: object
|
||||
AlertmanagertypesPostableChannel:
|
||||
oneOf:
|
||||
- required:
|
||||
- googlechat_configs
|
||||
- required:
|
||||
- discord_configs
|
||||
- required:
|
||||
@@ -192,6 +207,10 @@ components:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigEmailConfig'
|
||||
type: array
|
||||
googlechat_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/AlertmanagertypesGoogleChatReceiverConfig'
|
||||
type: array
|
||||
incidentio_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigIncidentioConfig'
|
||||
@@ -305,6 +324,87 @@ components:
|
||||
- channels
|
||||
- name
|
||||
type: object
|
||||
AlertmanagertypesReceiver:
|
||||
properties:
|
||||
discord_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigDiscordConfig'
|
||||
type: array
|
||||
email_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigEmailConfig'
|
||||
type: array
|
||||
googlechat_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/AlertmanagertypesGoogleChatReceiverConfig'
|
||||
type: array
|
||||
incidentio_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigIncidentioConfig'
|
||||
type: array
|
||||
jira_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigJiraConfig'
|
||||
type: array
|
||||
mattermost_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigMattermostConfig'
|
||||
type: array
|
||||
msteams_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigMSTeamsConfig'
|
||||
type: array
|
||||
msteamsv2_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigMSTeamsV2Config'
|
||||
type: array
|
||||
name:
|
||||
type: string
|
||||
opsgenie_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigOpsGenieConfig'
|
||||
type: array
|
||||
pagerduty_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigPagerdutyConfig'
|
||||
type: array
|
||||
pushover_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigPushoverConfig'
|
||||
type: array
|
||||
rocketchat_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigRocketchatConfig'
|
||||
type: array
|
||||
slack_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigSlackConfig'
|
||||
type: array
|
||||
sns_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigSNSConfig'
|
||||
type: array
|
||||
telegram_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigTelegramConfig'
|
||||
type: array
|
||||
victorops_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigVictorOpsConfig'
|
||||
type: array
|
||||
webex_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigWebexConfig'
|
||||
type: array
|
||||
webhook_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigWebhookConfig'
|
||||
type: array
|
||||
wechat_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigWechatConfig'
|
||||
type: array
|
||||
type: object
|
||||
AlertmanagertypesRecurrence:
|
||||
properties:
|
||||
duration:
|
||||
@@ -1849,83 +1949,6 @@ components:
|
||||
user_key_file:
|
||||
type: string
|
||||
type: object
|
||||
ConfigReceiver:
|
||||
properties:
|
||||
discord_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigDiscordConfig'
|
||||
type: array
|
||||
email_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigEmailConfig'
|
||||
type: array
|
||||
incidentio_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigIncidentioConfig'
|
||||
type: array
|
||||
jira_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigJiraConfig'
|
||||
type: array
|
||||
mattermost_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigMattermostConfig'
|
||||
type: array
|
||||
msteams_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigMSTeamsConfig'
|
||||
type: array
|
||||
msteamsv2_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigMSTeamsV2Config'
|
||||
type: array
|
||||
name:
|
||||
type: string
|
||||
opsgenie_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigOpsGenieConfig'
|
||||
type: array
|
||||
pagerduty_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigPagerdutyConfig'
|
||||
type: array
|
||||
pushover_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigPushoverConfig'
|
||||
type: array
|
||||
rocketchat_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigRocketchatConfig'
|
||||
type: array
|
||||
slack_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigSlackConfig'
|
||||
type: array
|
||||
sns_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigSNSConfig'
|
||||
type: array
|
||||
telegram_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigTelegramConfig'
|
||||
type: array
|
||||
victorops_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigVictorOpsConfig'
|
||||
type: array
|
||||
webex_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigWebexConfig'
|
||||
type: array
|
||||
webhook_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigWebhookConfig'
|
||||
type: array
|
||||
wechat_configs:
|
||||
items:
|
||||
$ref: '#/components/schemas/ConfigWechatConfig'
|
||||
type: array
|
||||
type: object
|
||||
ConfigRocketchatAttachmentAction:
|
||||
properties:
|
||||
image_url:
|
||||
@@ -7548,7 +7571,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ConfigReceiver'
|
||||
$ref: '#/components/schemas/AlertmanagertypesReceiver'
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
@@ -7599,7 +7622,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ConfigReceiver'
|
||||
$ref: '#/components/schemas/AlertmanagertypesReceiver'
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
@@ -7965,80 +7988,6 @@ paths:
|
||||
tags:
|
||||
- cloudintegration
|
||||
/api/v1/cloud_integrations/{cloud_provider}/accounts/{id}/services/{service_id}:
|
||||
get:
|
||||
deprecated: false
|
||||
description: This endpoint gets a service and its configuration for the specified
|
||||
cloud integration account
|
||||
operationId: GetAccountService
|
||||
parameters:
|
||||
- in: path
|
||||
name: cloud_provider
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: service_id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/CloudintegrationtypesService'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: OK
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Get service for account
|
||||
tags:
|
||||
- cloudintegration
|
||||
put:
|
||||
deprecated: false
|
||||
description: This endpoint updates a service for the specified cloud provider
|
||||
@@ -12279,7 +12228,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ConfigReceiver'
|
||||
$ref: '#/components/schemas/AlertmanagertypesReceiver'
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
|
||||
@@ -19,7 +19,7 @@ import type {
|
||||
|
||||
import type {
|
||||
AlertmanagertypesPostableChannelDTO,
|
||||
ConfigReceiverDTO,
|
||||
AlertmanagertypesReceiverDTO,
|
||||
CreateChannel201,
|
||||
DeleteChannelByIDPathParameters,
|
||||
GetChannelByID200,
|
||||
@@ -385,14 +385,14 @@ export const invalidateGetChannelByID = async (
|
||||
*/
|
||||
export const updateChannelByID = (
|
||||
{ id }: UpdateChannelByIDPathParameters,
|
||||
configReceiverDTO?: BodyType<ConfigReceiverDTO>,
|
||||
alertmanagertypesReceiverDTO?: BodyType<AlertmanagertypesReceiverDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/channels/${id}`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: configReceiverDTO,
|
||||
data: alertmanagertypesReceiverDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -406,7 +406,7 @@ export const getUpdateChannelByIDMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data?: BodyType<ConfigReceiverDTO>;
|
||||
data?: BodyType<AlertmanagertypesReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -415,7 +415,7 @@ export const getUpdateChannelByIDMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data?: BodyType<ConfigReceiverDTO>;
|
||||
data?: BodyType<AlertmanagertypesReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
@@ -432,7 +432,7 @@ export const getUpdateChannelByIDMutationOptions = <
|
||||
Awaited<ReturnType<typeof updateChannelByID>>,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data?: BodyType<ConfigReceiverDTO>;
|
||||
data?: BodyType<AlertmanagertypesReceiverDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
@@ -447,7 +447,7 @@ export type UpdateChannelByIDMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateChannelByID>>
|
||||
>;
|
||||
export type UpdateChannelByIDMutationBody =
|
||||
| BodyType<ConfigReceiverDTO>
|
||||
| BodyType<AlertmanagertypesReceiverDTO>
|
||||
| undefined;
|
||||
export type UpdateChannelByIDMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
@@ -463,7 +463,7 @@ export const useUpdateChannelByID = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data?: BodyType<ConfigReceiverDTO>;
|
||||
data?: BodyType<AlertmanagertypesReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -472,7 +472,7 @@ export const useUpdateChannelByID = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data?: BodyType<ConfigReceiverDTO>;
|
||||
data?: BodyType<AlertmanagertypesReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
@@ -483,14 +483,14 @@ export const useUpdateChannelByID = <
|
||||
* @summary Test notification channel
|
||||
*/
|
||||
export const testChannel = (
|
||||
configReceiverDTO?: BodyType<ConfigReceiverDTO>,
|
||||
alertmanagertypesReceiverDTO?: BodyType<AlertmanagertypesReceiverDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/channels/test`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: configReceiverDTO,
|
||||
data: alertmanagertypesReceiverDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -502,13 +502,13 @@ export const getTestChannelMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['testChannel'];
|
||||
@@ -522,7 +522,7 @@ export const getTestChannelMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
{ data?: BodyType<ConfigReceiverDTO> }
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -535,7 +535,9 @@ export const getTestChannelMutationOptions = <
|
||||
export type TestChannelMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof testChannel>>
|
||||
>;
|
||||
export type TestChannelMutationBody = BodyType<ConfigReceiverDTO> | undefined;
|
||||
export type TestChannelMutationBody =
|
||||
| BodyType<AlertmanagertypesReceiverDTO>
|
||||
| undefined;
|
||||
export type TestChannelMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -548,13 +550,13 @@ export const useTestChannel = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getTestChannelMutationOptions(options));
|
||||
@@ -565,14 +567,14 @@ export const useTestChannel = <
|
||||
* @summary Test notification channel (deprecated)
|
||||
*/
|
||||
export const testChannelDeprecated = (
|
||||
configReceiverDTO?: BodyType<ConfigReceiverDTO>,
|
||||
alertmanagertypesReceiverDTO?: BodyType<AlertmanagertypesReceiverDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/testChannel`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: configReceiverDTO,
|
||||
data: alertmanagertypesReceiverDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -584,13 +586,13 @@ export const getTestChannelDeprecatedMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['testChannelDeprecated'];
|
||||
@@ -604,7 +606,7 @@ export const getTestChannelDeprecatedMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
{ data?: BodyType<ConfigReceiverDTO> }
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -618,7 +620,7 @@ export type TestChannelDeprecatedMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>
|
||||
>;
|
||||
export type TestChannelDeprecatedMutationBody =
|
||||
| BodyType<ConfigReceiverDTO>
|
||||
| BodyType<AlertmanagertypesReceiverDTO>
|
||||
| undefined;
|
||||
export type TestChannelDeprecatedMutationError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
@@ -634,13 +636,13 @@ export const useTestChannelDeprecated = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getTestChannelDeprecatedMutationOptions(options));
|
||||
|
||||
@@ -31,8 +31,6 @@ import type {
|
||||
DisconnectAccountPathParameters,
|
||||
GetAccount200,
|
||||
GetAccountPathParameters,
|
||||
GetAccountService200,
|
||||
GetAccountServicePathParameters,
|
||||
GetConnectionCredentials200,
|
||||
GetConnectionCredentialsPathParameters,
|
||||
GetService200,
|
||||
@@ -633,117 +631,6 @@ export const useUpdateAccount = <
|
||||
> => {
|
||||
return useMutation(getUpdateAccountMutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* This endpoint gets a service and its configuration for the specified cloud integration account
|
||||
* @summary Get service for account
|
||||
*/
|
||||
export const getAccountService = (
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<GetAccountService200>({
|
||||
url: `/api/v1/cloud_integrations/${cloudProvider}/accounts/${id}/services/${serviceId}`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetAccountServiceQueryKey = ({
|
||||
cloudProvider,
|
||||
id,
|
||||
serviceId,
|
||||
}: GetAccountServicePathParameters) => {
|
||||
return [
|
||||
`/api/v1/cloud_integrations/${cloudProvider}/accounts/${id}/services/${serviceId}`,
|
||||
] as const;
|
||||
};
|
||||
|
||||
export const getGetAccountServiceQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ??
|
||||
getGetAccountServiceQueryKey({ cloudProvider, id, serviceId });
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof getAccountService>>
|
||||
> = ({ signal }) =>
|
||||
getAccountService({ cloudProvider, id, serviceId }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!(cloudProvider && id && serviceId),
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetAccountServiceQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getAccountService>>
|
||||
>;
|
||||
export type GetAccountServiceQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Get service for account
|
||||
*/
|
||||
|
||||
export function useGetAccountService<
|
||||
TData = Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetAccountServiceQueryOptions(
|
||||
{ cloudProvider, id, serviceId },
|
||||
options,
|
||||
);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get service for account
|
||||
*/
|
||||
export const invalidateGetAccountService = async (
|
||||
queryClient: QueryClient,
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetAccountServiceQueryKey({ cloudProvider, id, serviceId }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint updates a service for the specified cloud provider
|
||||
* @summary Update service
|
||||
|
||||
@@ -134,113 +134,6 @@ export interface AlertmanagertypesGettableRoutePolicyDTO {
|
||||
updatedBy?: string | null;
|
||||
}
|
||||
|
||||
export enum AlertmanagertypesMaintenanceKindDTO {
|
||||
fixed = 'fixed',
|
||||
recurring = 'recurring',
|
||||
}
|
||||
export enum AlertmanagertypesMaintenanceStatusDTO {
|
||||
active = 'active',
|
||||
upcoming = 'upcoming',
|
||||
expired = 'expired',
|
||||
}
|
||||
export enum AlertmanagertypesRepeatOnDTO {
|
||||
sunday = 'sunday',
|
||||
monday = 'monday',
|
||||
tuesday = 'tuesday',
|
||||
wednesday = 'wednesday',
|
||||
thursday = 'thursday',
|
||||
friday = 'friday',
|
||||
saturday = 'saturday',
|
||||
}
|
||||
export enum AlertmanagertypesRepeatTypeDTO {
|
||||
daily = 'daily',
|
||||
weekly = 'weekly',
|
||||
monthly = 'monthly',
|
||||
}
|
||||
export interface AlertmanagertypesRecurrenceDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
duration: string;
|
||||
/**
|
||||
* @type string,null
|
||||
* @format date-time
|
||||
*/
|
||||
endTime?: string | null;
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
repeatOn?: AlertmanagertypesRepeatOnDTO[] | null;
|
||||
repeatType: AlertmanagertypesRepeatTypeDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
startTime: string;
|
||||
}
|
||||
|
||||
export interface AlertmanagertypesScheduleDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
endTime?: string;
|
||||
recurrence?: AlertmanagertypesRecurrenceDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
startTime?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
timezone: string;
|
||||
}
|
||||
|
||||
export interface AlertmanagertypesPlannedMaintenanceDTO {
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
alertIds?: string[] | null;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
createdBy?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
kind: AlertmanagertypesMaintenanceKindDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
schedule: AlertmanagertypesScheduleDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
scope?: string;
|
||||
status: AlertmanagertypesMaintenanceStatusDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
updatedBy?: string;
|
||||
}
|
||||
|
||||
export interface ConfigAuthorizationDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -475,6 +368,130 @@ export interface ConfigSecretURLDTO {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface AlertmanagertypesGoogleChatReceiverConfigDTO {
|
||||
http_config?: ConfigHTTPClientConfigDTO;
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
send_resolved?: boolean;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
text?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
title?: string;
|
||||
webhook_url?: ConfigSecretURLDTO;
|
||||
}
|
||||
|
||||
export enum AlertmanagertypesMaintenanceKindDTO {
|
||||
fixed = 'fixed',
|
||||
recurring = 'recurring',
|
||||
}
|
||||
export enum AlertmanagertypesMaintenanceStatusDTO {
|
||||
active = 'active',
|
||||
upcoming = 'upcoming',
|
||||
expired = 'expired',
|
||||
}
|
||||
export enum AlertmanagertypesRepeatOnDTO {
|
||||
sunday = 'sunday',
|
||||
monday = 'monday',
|
||||
tuesday = 'tuesday',
|
||||
wednesday = 'wednesday',
|
||||
thursday = 'thursday',
|
||||
friday = 'friday',
|
||||
saturday = 'saturday',
|
||||
}
|
||||
export enum AlertmanagertypesRepeatTypeDTO {
|
||||
daily = 'daily',
|
||||
weekly = 'weekly',
|
||||
monthly = 'monthly',
|
||||
}
|
||||
export interface AlertmanagertypesRecurrenceDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
duration: string;
|
||||
/**
|
||||
* @type string,null
|
||||
* @format date-time
|
||||
*/
|
||||
endTime?: string | null;
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
repeatOn?: AlertmanagertypesRepeatOnDTO[] | null;
|
||||
repeatType: AlertmanagertypesRepeatTypeDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
startTime: string;
|
||||
}
|
||||
|
||||
export interface AlertmanagertypesScheduleDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
endTime?: string;
|
||||
recurrence?: AlertmanagertypesRecurrenceDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
startTime?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
timezone: string;
|
||||
}
|
||||
|
||||
export interface AlertmanagertypesPlannedMaintenanceDTO {
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
alertIds?: string[] | null;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
createdBy?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
kind: AlertmanagertypesMaintenanceKindDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
schedule: AlertmanagertypesScheduleDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
scope?: string;
|
||||
status: AlertmanagertypesMaintenanceStatusDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
updatedBy?: string;
|
||||
}
|
||||
|
||||
export interface ConfigDiscordConfigDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -1634,6 +1651,10 @@ export type AlertmanagertypesPostableChannelDTO = unknown & {
|
||||
* @type array
|
||||
*/
|
||||
email_configs?: ConfigEmailConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
googlechat_configs?: AlertmanagertypesGoogleChatReceiverConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
@@ -1748,6 +1769,89 @@ export interface AlertmanagertypesPostableRoutePolicyDTO {
|
||||
tags?: string[] | null;
|
||||
}
|
||||
|
||||
export interface AlertmanagertypesReceiverDTO {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
discord_configs?: ConfigDiscordConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
email_configs?: ConfigEmailConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
googlechat_configs?: AlertmanagertypesGoogleChatReceiverConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
incidentio_configs?: ConfigIncidentioConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
jira_configs?: ConfigJiraConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
mattermost_configs?: ConfigMattermostConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
msteams_configs?: ConfigMSTeamsConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
msteamsv2_configs?: ConfigMSTeamsV2ConfigDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
opsgenie_configs?: ConfigOpsGenieConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
pagerduty_configs?: ConfigPagerdutyConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
pushover_configs?: ConfigPushoverConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
rocketchat_configs?: ConfigRocketchatConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
slack_configs?: ConfigSlackConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
sns_configs?: ConfigSNSConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
telegram_configs?: ConfigTelegramConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
victorops_configs?: ConfigVictorOpsConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
webex_configs?: ConfigWebexConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
webhook_configs?: ConfigWebhookConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
wechat_configs?: ConfigWechatConfigDTO[];
|
||||
}
|
||||
|
||||
export interface AuthtypesAttributeMappingDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -2927,85 +3031,6 @@ export interface CommonJSONRefDTO {
|
||||
$ref?: string;
|
||||
}
|
||||
|
||||
export interface ConfigReceiverDTO {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
discord_configs?: ConfigDiscordConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
email_configs?: ConfigEmailConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
incidentio_configs?: ConfigIncidentioConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
jira_configs?: ConfigJiraConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
mattermost_configs?: ConfigMattermostConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
msteams_configs?: ConfigMSTeamsConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
msteamsv2_configs?: ConfigMSTeamsV2ConfigDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
opsgenie_configs?: ConfigOpsGenieConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
pagerduty_configs?: ConfigPagerdutyConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
pushover_configs?: ConfigPushoverConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
rocketchat_configs?: ConfigRocketchatConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
slack_configs?: ConfigSlackConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
sns_configs?: ConfigSNSConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
telegram_configs?: ConfigTelegramConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
victorops_configs?: ConfigVictorOpsConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
webex_configs?: ConfigWebexConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
webhook_configs?: ConfigWebhookConfigDTO[];
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
wechat_configs?: ConfigWechatConfigDTO[];
|
||||
}
|
||||
|
||||
export interface CoretypesObjectGroupDTO {
|
||||
resource: CoretypesResourceRefDTO;
|
||||
/**
|
||||
@@ -8566,19 +8591,6 @@ export type UpdateAccountPathParameters = {
|
||||
cloudProvider: string;
|
||||
id: string;
|
||||
};
|
||||
export type GetAccountServicePathParameters = {
|
||||
cloudProvider: string;
|
||||
id: string;
|
||||
serviceId: string;
|
||||
};
|
||||
export type GetAccountService200 = {
|
||||
data: CloudintegrationtypesServiceDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type UpdateServicePathParameters = {
|
||||
cloudProvider: string;
|
||||
id: string;
|
||||
|
||||
@@ -41,22 +41,14 @@ $item-spacing: 8px;
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
height: auto;
|
||||
color: var(--l1-foreground);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
letter-spacing: -0.07px;
|
||||
padding: 0;
|
||||
|
||||
&:focus,
|
||||
&:focus-visible,
|
||||
&:hover {
|
||||
border: none;
|
||||
&.ant-input:focus {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Input } from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
import { TimezonePickerShortcuts } from 'constants/shortcuts/TimezonePickerShortcuts';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Card, Form } from 'antd';
|
||||
import { Card, Form, Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button } from 'antd';
|
||||
import { Button, Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import { X } from '@signozhq/icons';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, InputNumber, Popover, Tooltip } from 'antd';
|
||||
import { Button, Input, InputNumber, Popover, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import cx from 'classnames';
|
||||
|
||||
@@ -266,14 +266,6 @@
|
||||
border-left: transparent;
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
|
||||
&:focus:not(:focus-visible),
|
||||
&.ant-btn:focus:not(:focus-visible) {
|
||||
border-color: var(--l2-border);
|
||||
border-left-color: transparent;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -299,21 +291,5 @@
|
||||
.cm-placeholder {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
$add-on-row-height: 38px;
|
||||
|
||||
.periscope-input-with-label {
|
||||
.input {
|
||||
.ant-select {
|
||||
height: $add-on-row-height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-with-label {
|
||||
.input {
|
||||
height: $add-on-row-height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,23 +4,6 @@
|
||||
padding: 12px;
|
||||
gap: 12px;
|
||||
border-bottom: 1px solid var(--l1-border);
|
||||
|
||||
.search {
|
||||
input {
|
||||
--input-background: var(--l2-background);
|
||||
--input-hover-background: var(--l2-background);
|
||||
--input-focus-background: var(--l2-background);
|
||||
&::placeholder {
|
||||
color: var(--l3-foreground);
|
||||
}
|
||||
--input-font-size: 14px;
|
||||
--input-border-color: var(--l1-border);
|
||||
--input-focus-border-color: var(--primary-background);
|
||||
--input-focus-outline-width: 0;
|
||||
--input-focus-outline-offset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-header-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable sonarjs/no-identical-functions */
|
||||
import { Fragment, useMemo, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Skeleton } from 'antd';
|
||||
import { Button, Input, Skeleton } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button } from 'antd';
|
||||
import { Button, Input } from 'antd';
|
||||
import { Check, TableColumnsSplit, X } from '@signozhq/icons';
|
||||
import { Filter as FilterType } from 'types/api/quickFilters/getCustomFilters';
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Select, Tooltip } from 'antd';
|
||||
import { Button, Input, Select, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { CircleX, Trash } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Collapse } from 'antd';
|
||||
import { Collapse, Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
import { useCreateAlertState } from '../context';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Select } from 'antd';
|
||||
import { Input, Select } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
import { ADVANCED_OPTIONS_TIME_UNIT_OPTIONS } from '../../context/constants';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Input } from 'antd';
|
||||
|
||||
import './TimeInput.scss';
|
||||
|
||||
export interface TimeInputProps {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Select } from 'antd';
|
||||
import { Input, Select } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
import { useCreateAlertState } from '../context';
|
||||
|
||||
@@ -16,10 +16,9 @@ import {
|
||||
Plus,
|
||||
X,
|
||||
} from '@signozhq/icons';
|
||||
import { Button, Card, Modal, Popover, Tooltip } from 'antd';
|
||||
import { Button, Card, Input, Modal, Popover, Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import ConfigureIcon from 'assets/Integrations/ConfigureIcon';
|
||||
import { PANEL_GROUP_TYPES, PANEL_TYPES } from 'constants/queryBuilder';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button } from 'antd';
|
||||
import { Button, Input } from 'antd';
|
||||
import { PrecisionOption, PrecisionOptionsEnum } from 'components/Graph/types';
|
||||
import { ResizeTable } from 'components/ResizeTable';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
|
||||
@@ -22,6 +22,7 @@ import { Color } from '@signozhq/design-tokens';
|
||||
import {
|
||||
Button,
|
||||
ColorPicker,
|
||||
Input,
|
||||
Modal,
|
||||
RefSelectProps,
|
||||
Select,
|
||||
@@ -29,7 +30,6 @@ import {
|
||||
} from 'antd';
|
||||
import { Divider } from '@signozhq/ui/divider';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import setLocalStorageKey from 'api/browser/localstorage/set';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form } from 'antd';
|
||||
import { Form, Input } from 'antd';
|
||||
|
||||
import { EmailChannel } from '../../CreateAlertChannels/config';
|
||||
|
||||
function EmailForm({ setSelectedConfig }: EmailFormProps): JSX.Element {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form } from 'antd';
|
||||
import { Form, Input } from 'antd';
|
||||
import { MarkdownRenderer } from 'components/MarkdownRenderer/MarkdownRenderer';
|
||||
|
||||
import { WebhookChannel } from '../../CreateAlertChannels/config';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Dispatch, ReactElement, SetStateAction } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form, FormInstance, Input, Select } from 'antd';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Form, FormInstance, Select } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import type { Store } from 'antd/lib/form/interface';
|
||||
import ROUTES from 'constants/routes';
|
||||
|
||||
@@ -6,8 +6,7 @@ import { useIsFetching } from 'react-query';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Form, Modal } from 'antd';
|
||||
import { Button, Form, Input, Modal } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
|
||||
@@ -5,12 +5,12 @@ import { useCopyToClipboard } from 'react-use';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import {
|
||||
Col,
|
||||
Collapse,
|
||||
DatePicker,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Modal,
|
||||
Row,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form } from 'antd';
|
||||
import { Form, Input } from 'antd';
|
||||
import { CloudintegrationtypesCredentialsDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
|
||||
function RenderConnectionFields({
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Form } from 'antd';
|
||||
import { Button, Form, Input } from 'antd';
|
||||
import apply from 'api/v3/licenses/post';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
import { ChangeEvent, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Modal } from 'antd';
|
||||
import { Button, Input, Modal } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import ApacheIcon from 'assets/CustomIcons/ApacheIcon';
|
||||
import DockerIcon from 'assets/CustomIcons/DockerIcon';
|
||||
|
||||
@@ -12,9 +12,17 @@ import { useTranslation } from 'react-i18next';
|
||||
import { generatePath } from 'react-router-dom';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { DropdownMenuSimple, type MenuItem } from '@signozhq/ui/dropdown-menu';
|
||||
import { Button, Flex, Modal, Popover, Skeleton, Table, Tooltip } from 'antd';
|
||||
import {
|
||||
Button,
|
||||
Flex,
|
||||
Input,
|
||||
Modal,
|
||||
Popover,
|
||||
Skeleton,
|
||||
Table,
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LoaderCircle, Check } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Space } from 'antd';
|
||||
import { Button, Input, Space } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
|
||||
@@ -2,9 +2,8 @@ import { ReactNode, useState } from 'react';
|
||||
import MEditor, { EditorProps, Monaco } from '@monaco-editor/react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Collapse } from 'antd';
|
||||
import { Collapse, Input } from 'antd';
|
||||
import { Divider } from '@signozhq/ui/divider';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
@@ -2,8 +2,7 @@ import { ChangeEvent, useCallback, useState } from 'react';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { CirclePlus, X } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Col } from 'antd';
|
||||
import { Col, Input } from 'antd';
|
||||
import CategoryHeading from 'components/Logs/CategoryHeading';
|
||||
import { fieldSearchFilter } from 'lib/logs/fieldSearch';
|
||||
import { AppState } from 'store/reducers';
|
||||
|
||||
@@ -2,8 +2,7 @@ import { useCallback, useMemo, useState } from 'react';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { SquareX, X } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Select } from 'antd';
|
||||
import { Button, Input, Select } from 'antd';
|
||||
import CategoryHeading from 'components/Logs/CategoryHeading';
|
||||
import {
|
||||
ConditionalOperators,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
// TODO(@signozhq/ui-input): migrate this <Input> once @signozhq/ui Input
|
||||
// supports the `onWheel` handler (used to blur on scroll for number inputs).
|
||||
import { Input, Select } from 'antd';
|
||||
import { Select } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { TIME_AGGREGATION_OPTIONS } from './constants';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useQueryClient } from 'react-query';
|
||||
import type { TableColumnsType as ColumnsType } from 'antd';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Collapse, Select, Spin } from 'antd';
|
||||
import { Button, Collapse, Input, Select, Spin } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import {
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
DropResult,
|
||||
} from 'react-beautiful-dnd';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { Button, Input, Tooltip } from 'antd';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
// TODO(@signozhq/ui-input): migrate <Input> once @signozhq/ui Input
|
||||
// supports the `spellCheck` prop on the URL input below.
|
||||
import { Button, Col, Form, Input, Input as AntInput, Row } from 'antd';
|
||||
import { Button, Col, Form, Input as AntInput, Input, Row } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { CONTEXT_LINK_FIELDS } from 'container/NewWidget/RightContainer/ContextLinks/constants';
|
||||
import {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Blocks, Check, LoaderCircle } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Card, Form, Select, Space } from 'antd';
|
||||
import { Button, Card, Form, Input, Select, Space } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Check, Server, LoaderCircle } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Card, Form, Space } from 'antd';
|
||||
import { Button, Card, Form, Input, Space } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Plus, Trash2 } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Form, FormInstance, Select, Space } from 'antd';
|
||||
import { Button, Form, FormInstance, Input, Select, Space } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { requireErrorMessage } from 'utils/form/requireErrorMessage';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form } from 'antd';
|
||||
import { Form, Input } from 'antd';
|
||||
|
||||
import { ProcessorFormField } from '../../AddNewProcessor/config';
|
||||
import { formValidationRules } from '../../config';
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { ChangeEventHandler, useState } from 'react';
|
||||
// TODO(@signozhq/ui-input): migrate to @signozhq/ui Input once the antd
|
||||
// `InputProps` spread (`size`, etc.) is no longer needed on this wrapper.
|
||||
import { Input, InputProps } from 'antd';
|
||||
|
||||
function CSVInput({ value, onChange, ...otherProps }: InputProps): JSX.Element {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Info } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Flex, Form, Space, Tooltip } from 'antd';
|
||||
import { Flex, Form, Input, Space, Tooltip } from 'antd';
|
||||
import { ProcessorData } from 'types/api/pipeline/def';
|
||||
|
||||
import { PREDEFINED_MAPPING } from '../config';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form, Input, Select, Space } from 'antd';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Form, Select, Space } from 'antd';
|
||||
import { ModalFooterTitle } from 'container/PipelinePage/styles';
|
||||
import { ProcessorData } from 'types/api/pipeline/def';
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@ import React, { ChangeEvent, useEffect, useState } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Plus, Search } from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Flex, Form, Tooltip } from 'antd';
|
||||
import { Button, Flex, Form, Input, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import {
|
||||
useDeleteDowntimeScheduleByID,
|
||||
|
||||
@@ -8,16 +8,4 @@
|
||||
grid-template-columns: 60% 35%;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
|
||||
.input-with-label {
|
||||
.label {
|
||||
box-sizing: border-box;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.input {
|
||||
box-sizing: border-box;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Skeleton } from 'antd';
|
||||
import { Input, Skeleton } from 'antd';
|
||||
import { getKeySuggestions } from 'api/querySuggestions/getKeySuggestions';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
import { QUERY_BUILDER_KEY_TYPES } from 'constants/antlrQueryConstants';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { ChangeEvent, useMemo } from 'react';
|
||||
import { Plus, Search } from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Flex, Tooltip } from 'antd';
|
||||
import { Button, Flex, Input, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { USER_ROLES } from 'types/roles';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import CopyClipboardHOC from 'components/Logs/CopyClipboardHOC';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Collapse, Modal } from 'antd';
|
||||
import { Collapse, Input, Modal } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { getYAxisFormattedValue } from 'components/Graph/yAxisConfig';
|
||||
import { Diamond } from '@signozhq/icons';
|
||||
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Input,
|
||||
Modal,
|
||||
Select,
|
||||
Skeleton,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// TODO(@signozhq/ui-input): migrate this styled(Input) once @signozhq/ui
|
||||
// Input supports `addonAfter` (the consumer renders `<InputComponent addonAfter="ms">`).
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const DurationText = styled.div`
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
import { useQuery } from 'react-query';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { AutoComplete } from 'antd';
|
||||
import { AutoComplete, Input } from 'antd';
|
||||
import getTagFilters from 'api/trace/getTagFilter';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
@@ -2,8 +2,7 @@ import { useMemo, useState } from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { AutoComplete, Space } from 'antd';
|
||||
import { AutoComplete, Input, Space } from 'antd';
|
||||
import getTagFilters from 'api/trace/getTagFilter';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ChangeEvent, useEffect, useMemo, useState } from 'react';
|
||||
import { ArrowLeft, Check, Loader, Plus, Search } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Spin } from 'antd';
|
||||
import { Button, Input, Spin } from 'antd';
|
||||
import cx from 'classnames';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
import SignozModal from 'components/SignozModal/SignozModal';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Input } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const InputComponent = styled(Input)`
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Select } from 'antd';
|
||||
import { Input, Select } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
import './DropRateView.styles.scss';
|
||||
|
||||
@@ -28,10 +28,6 @@
|
||||
.learn-more {
|
||||
font-size: 14px;
|
||||
}
|
||||
.search-input-container {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper {
|
||||
margin-top: 16px;
|
||||
|
||||
@@ -3,8 +3,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { ColorPicker, Modal, Table, TableProps } from 'antd';
|
||||
import { ColorPicker, Input, Modal, Table, TableProps } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import {
|
||||
@@ -312,15 +311,12 @@ function SaveView(): JSX.Element {
|
||||
Learn more
|
||||
</Typography.Link>
|
||||
</Typography.Text>
|
||||
<div className="search-input-container">
|
||||
<Input
|
||||
placeholder="Search for views..."
|
||||
prefix={<Search size={12} color={Color.BG_VANILLA_400} />}
|
||||
value={searchValue}
|
||||
onChange={handleSearch}
|
||||
className="search-input"
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
placeholder="Search for views..."
|
||||
prefix={<Search size={12} color={Color.BG_VANILLA_400} />}
|
||||
value={searchValue}
|
||||
onChange={handleSearch}
|
||||
/>
|
||||
|
||||
<Table
|
||||
columns={columns}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Select, Skeleton } from 'antd';
|
||||
import { Input, Select, Skeleton } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import cx from 'classnames';
|
||||
import { getYAxisFormattedValue } from 'components/Graph/yAxisConfig';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ChangeEvent, useEffect, useMemo, useState } from 'react';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Spin } from 'antd';
|
||||
import { Input, Spin } from 'antd';
|
||||
import cx from 'classnames';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
import SignozModal from 'components/SignozModal/SignozModal';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { useQueryClient } from 'react-query';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Input } from 'antd';
|
||||
import SignozModal from 'components/SignozModal/SignozModal';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import { useRenameFunnel } from 'hooks/TracesFunnels/useFunnels';
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
.ant-input-prefix {
|
||||
margin-inline-end: 6px;
|
||||
}
|
||||
|
||||
&,
|
||||
input {
|
||||
font-family: Inter;
|
||||
background: var(--l2-background);
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Popover, Tooltip } from 'antd';
|
||||
import { Button, Input, Popover, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { ArrowDownWideNarrow, Check, Plus, Search } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
|
||||
@@ -204,12 +204,5 @@
|
||||
background: var(--l2-background);
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
|
||||
&:focus:not(:focus-visible),
|
||||
&.ant-btn:focus:not(:focus-visible) {
|
||||
border-color: var(--l2-border);
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ type Alertmanager interface {
|
||||
PutAlerts(context.Context, string, alertmanagertypes.PostableAlerts) error
|
||||
|
||||
// TestReceiver sends a test alert to a receiver.
|
||||
TestReceiver(context.Context, string, alertmanagertypes.Receiver) error
|
||||
TestReceiver(context.Context, string, *alertmanagertypes.Receiver) error
|
||||
|
||||
// TestAlert sends an alert to a list of receivers.
|
||||
TestAlert(ctx context.Context, orgID string, ruleID string, receiversMap map[*alertmanagertypes.PostableAlert][]string) error
|
||||
@@ -41,10 +41,10 @@ type Alertmanager interface {
|
||||
GetChannelByID(context.Context, string, valuer.UUID) (*alertmanagertypes.Channel, error)
|
||||
|
||||
// UpdateChannel updates a channel for the organization.
|
||||
UpdateChannelByReceiverAndID(context.Context, string, alertmanagertypes.Receiver, valuer.UUID) error
|
||||
UpdateChannelByReceiverAndID(context.Context, string, *alertmanagertypes.Receiver, valuer.UUID) error
|
||||
|
||||
// CreateChannel creates a channel for the organization.
|
||||
CreateChannel(context.Context, string, alertmanagertypes.Receiver) (*alertmanagertypes.Channel, error)
|
||||
CreateChannel(context.Context, string, *alertmanagertypes.Receiver) (*alertmanagertypes.Channel, error)
|
||||
|
||||
// DeleteChannelByID deletes a channel for the organization.
|
||||
DeleteChannelByID(context.Context, string, valuer.UUID) error
|
||||
|
||||
@@ -26,8 +26,8 @@ var customNotifierIntegrations = []string{
|
||||
msteamsv2.Integration,
|
||||
}
|
||||
|
||||
func NewReceiverIntegrations(nc alertmanagertypes.Receiver, tmpl *template.Template, logger *slog.Logger, templater alertmanagertypes.Templater) ([]notify.Integration, error) {
|
||||
upstreamIntegrations, err := receiver.BuildReceiverIntegrations(nc, tmpl, logger)
|
||||
func NewReceiverIntegrations(nc *alertmanagertypes.Receiver, tmpl *template.Template, logger *slog.Logger, templater alertmanagertypes.Templater) ([]notify.Integration, error) {
|
||||
upstreamIntegrations, err := receiver.BuildReceiverIntegrations(*nc.Receiver, tmpl, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -275,7 +275,11 @@ func (server *Server) SetConfig(ctx context.Context, alertmanagerConfig *alertma
|
||||
server.logger.InfoContext(ctx, "skipping creation of receiver not referenced by any route", slog.String("receiver", rcv.Name))
|
||||
continue
|
||||
}
|
||||
integrations, err := alertmanagernotify.NewReceiverIntegrations(rcv, server.tmpl, server.logger, server.templater)
|
||||
extendedRcv, err := alertmanagerConfig.GetReceiver(rcv.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
integrations, err := alertmanagernotify.NewReceiverIntegrations(extendedRcv, server.tmpl, server.logger, server.templater)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -350,7 +354,7 @@ func (server *Server) SetConfig(ctx context.Context, alertmanagerConfig *alertma
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) TestReceiver(ctx context.Context, receiver alertmanagertypes.Receiver) error {
|
||||
func (server *Server) TestReceiver(ctx context.Context, receiver *alertmanagertypes.Receiver) error {
|
||||
testAlert := alertmanagertypes.NewTestAlert(receiver, time.Now(), time.Now())
|
||||
return alertmanagertypes.TestReceiver(ctx, receiver, alertmanagernotify.NewReceiverIntegrations, server.alertmanagerConfig, server.tmpl, server.logger, server.templater, testAlert.Labels, testAlert)
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ func TestServerTestReceiverTypeWebhook(t *testing.T) {
|
||||
webhookURL, err := url.Parse("http://" + webhookListener.Addr().String() + "/webhook")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = server.TestReceiver(context.Background(), alertmanagertypes.Receiver{
|
||||
err = server.TestReceiver(context.Background(), &alertmanagertypes.Receiver{Receiver: &config.Receiver{
|
||||
Name: "test-receiver",
|
||||
WebhookConfigs: []*config.WebhookConfig{
|
||||
{
|
||||
@@ -83,7 +83,7 @@ func TestServerTestReceiverTypeWebhook(t *testing.T) {
|
||||
URL: config.SecretTemplateURL(webhookURL.String()),
|
||||
},
|
||||
},
|
||||
})
|
||||
}})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, requestBody.String(), "test-receiver")
|
||||
@@ -101,7 +101,7 @@ func TestServerPutAlerts(t *testing.T) {
|
||||
amConfig, err := alertmanagertypes.NewDefaultConfig(srvCfg.Global, srvCfg.Route, "1")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, amConfig.CreateReceiver(alertmanagertypes.Receiver{
|
||||
require.NoError(t, amConfig.CreateReceiver(&alertmanagertypes.Receiver{Receiver: &config.Receiver{
|
||||
Name: "test-receiver",
|
||||
WebhookConfigs: []*config.WebhookConfig{
|
||||
{
|
||||
@@ -109,7 +109,7 @@ func TestServerPutAlerts(t *testing.T) {
|
||||
URL: config.SecretTemplateURL("http://localhost/test-receiver"),
|
||||
},
|
||||
},
|
||||
}))
|
||||
}}))
|
||||
|
||||
require.NoError(t, server.SetConfig(context.Background(), amConfig))
|
||||
|
||||
@@ -181,7 +181,7 @@ func TestServerTestAlert(t *testing.T) {
|
||||
webhook2URL, err := url.Parse("http://" + webhook2Listener.Addr().String() + "/webhook")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, amConfig.CreateReceiver(alertmanagertypes.Receiver{
|
||||
require.NoError(t, amConfig.CreateReceiver(&alertmanagertypes.Receiver{Receiver: &config.Receiver{
|
||||
Name: "receiver-1",
|
||||
WebhookConfigs: []*config.WebhookConfig{
|
||||
{
|
||||
@@ -189,9 +189,9 @@ func TestServerTestAlert(t *testing.T) {
|
||||
URL: config.SecretTemplateURL(webhook1URL.String()),
|
||||
},
|
||||
},
|
||||
}))
|
||||
}}))
|
||||
|
||||
require.NoError(t, amConfig.CreateReceiver(alertmanagertypes.Receiver{
|
||||
require.NoError(t, amConfig.CreateReceiver(&alertmanagertypes.Receiver{Receiver: &config.Receiver{
|
||||
Name: "receiver-2",
|
||||
WebhookConfigs: []*config.WebhookConfig{
|
||||
{
|
||||
@@ -199,7 +199,7 @@ func TestServerTestAlert(t *testing.T) {
|
||||
URL: config.SecretTemplateURL(webhook2URL.String()),
|
||||
},
|
||||
},
|
||||
}))
|
||||
}}))
|
||||
|
||||
require.NoError(t, server.SetConfig(context.Background(), amConfig))
|
||||
defer func() {
|
||||
@@ -273,7 +273,7 @@ func TestServerTestAlertContinuesOnFailure(t *testing.T) {
|
||||
webhookURL, err := url.Parse("http://" + webhookListener.Addr().String() + "/webhook")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, amConfig.CreateReceiver(alertmanagertypes.Receiver{
|
||||
require.NoError(t, amConfig.CreateReceiver(&alertmanagertypes.Receiver{Receiver: &config.Receiver{
|
||||
Name: "working-receiver",
|
||||
WebhookConfigs: []*config.WebhookConfig{
|
||||
{
|
||||
@@ -281,9 +281,9 @@ func TestServerTestAlertContinuesOnFailure(t *testing.T) {
|
||||
URL: config.SecretTemplateURL(webhookURL.String()),
|
||||
},
|
||||
},
|
||||
}))
|
||||
}}))
|
||||
|
||||
require.NoError(t, amConfig.CreateReceiver(alertmanagertypes.Receiver{
|
||||
require.NoError(t, amConfig.CreateReceiver(&alertmanagertypes.Receiver{Receiver: &config.Receiver{
|
||||
Name: "failing-receiver",
|
||||
WebhookConfigs: []*config.WebhookConfig{
|
||||
{
|
||||
@@ -291,7 +291,7 @@ func TestServerTestAlertContinuesOnFailure(t *testing.T) {
|
||||
URL: config.SecretTemplateURL("http://localhost:1/webhook"),
|
||||
},
|
||||
},
|
||||
}))
|
||||
}}))
|
||||
|
||||
require.NoError(t, server.SetConfig(context.Background(), amConfig))
|
||||
defer func() {
|
||||
|
||||
@@ -155,7 +155,7 @@ func (_c *MockAlertmanager_Config_Call) RunAndReturn(run func() alertmanagerserv
|
||||
}
|
||||
|
||||
// CreateChannel provides a mock function for the type MockAlertmanager
|
||||
func (_mock *MockAlertmanager) CreateChannel(context1 context.Context, s string, v alertmanagertypes.Receiver) (*alertmanagertypes.Channel, error) {
|
||||
func (_mock *MockAlertmanager) CreateChannel(context1 context.Context, s string, v *alertmanagertypes.Receiver) (*alertmanagertypes.Channel, error) {
|
||||
ret := _mock.Called(context1, s, v)
|
||||
|
||||
if len(ret) == 0 {
|
||||
@@ -164,17 +164,17 @@ func (_mock *MockAlertmanager) CreateChannel(context1 context.Context, s string,
|
||||
|
||||
var r0 *alertmanagertypes.Channel
|
||||
var r1 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, alertmanagertypes.Receiver) (*alertmanagertypes.Channel, error)); ok {
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, *alertmanagertypes.Receiver) (*alertmanagertypes.Channel, error)); ok {
|
||||
return returnFunc(context1, s, v)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, alertmanagertypes.Receiver) *alertmanagertypes.Channel); ok {
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, *alertmanagertypes.Receiver) *alertmanagertypes.Channel); ok {
|
||||
r0 = returnFunc(context1, s, v)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*alertmanagertypes.Channel)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, string, alertmanagertypes.Receiver) error); ok {
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, string, *alertmanagertypes.Receiver) error); ok {
|
||||
r1 = returnFunc(context1, s, v)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -190,12 +190,12 @@ type MockAlertmanager_CreateChannel_Call struct {
|
||||
// CreateChannel is a helper method to define mock.On call
|
||||
// - context1 context.Context
|
||||
// - s string
|
||||
// - v alertmanagertypes.Receiver
|
||||
// - v *alertmanagertypes.Receiver
|
||||
func (_e *MockAlertmanager_Expecter) CreateChannel(context1 interface{}, s interface{}, v interface{}) *MockAlertmanager_CreateChannel_Call {
|
||||
return &MockAlertmanager_CreateChannel_Call{Call: _e.mock.On("CreateChannel", context1, s, v)}
|
||||
}
|
||||
|
||||
func (_c *MockAlertmanager_CreateChannel_Call) Run(run func(context1 context.Context, s string, v alertmanagertypes.Receiver)) *MockAlertmanager_CreateChannel_Call {
|
||||
func (_c *MockAlertmanager_CreateChannel_Call) Run(run func(context1 context.Context, s string, v *alertmanagertypes.Receiver)) *MockAlertmanager_CreateChannel_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
@@ -205,9 +205,9 @@ func (_c *MockAlertmanager_CreateChannel_Call) Run(run func(context1 context.Con
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(string)
|
||||
}
|
||||
var arg2 alertmanagertypes.Receiver
|
||||
var arg2 *alertmanagertypes.Receiver
|
||||
if args[2] != nil {
|
||||
arg2 = args[2].(alertmanagertypes.Receiver)
|
||||
arg2 = args[2].(*alertmanagertypes.Receiver)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
@@ -223,7 +223,7 @@ func (_c *MockAlertmanager_CreateChannel_Call) Return(channel *alertmanagertypes
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockAlertmanager_CreateChannel_Call) RunAndReturn(run func(context1 context.Context, s string, v alertmanagertypes.Receiver) (*alertmanagertypes.Channel, error)) *MockAlertmanager_CreateChannel_Call {
|
||||
func (_c *MockAlertmanager_CreateChannel_Call) RunAndReturn(run func(context1 context.Context, s string, v *alertmanagertypes.Receiver) (*alertmanagertypes.Channel, error)) *MockAlertmanager_CreateChannel_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
@@ -1624,7 +1624,7 @@ func (_c *MockAlertmanager_TestAlert_Call) RunAndReturn(run func(ctx context.Con
|
||||
}
|
||||
|
||||
// TestReceiver provides a mock function for the type MockAlertmanager
|
||||
func (_mock *MockAlertmanager) TestReceiver(context1 context.Context, s string, v alertmanagertypes.Receiver) error {
|
||||
func (_mock *MockAlertmanager) TestReceiver(context1 context.Context, s string, v *alertmanagertypes.Receiver) error {
|
||||
ret := _mock.Called(context1, s, v)
|
||||
|
||||
if len(ret) == 0 {
|
||||
@@ -1632,7 +1632,7 @@ func (_mock *MockAlertmanager) TestReceiver(context1 context.Context, s string,
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, alertmanagertypes.Receiver) error); ok {
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, *alertmanagertypes.Receiver) error); ok {
|
||||
r0 = returnFunc(context1, s, v)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
@@ -1648,12 +1648,12 @@ type MockAlertmanager_TestReceiver_Call struct {
|
||||
// TestReceiver is a helper method to define mock.On call
|
||||
// - context1 context.Context
|
||||
// - s string
|
||||
// - v alertmanagertypes.Receiver
|
||||
// - v *alertmanagertypes.Receiver
|
||||
func (_e *MockAlertmanager_Expecter) TestReceiver(context1 interface{}, s interface{}, v interface{}) *MockAlertmanager_TestReceiver_Call {
|
||||
return &MockAlertmanager_TestReceiver_Call{Call: _e.mock.On("TestReceiver", context1, s, v)}
|
||||
}
|
||||
|
||||
func (_c *MockAlertmanager_TestReceiver_Call) Run(run func(context1 context.Context, s string, v alertmanagertypes.Receiver)) *MockAlertmanager_TestReceiver_Call {
|
||||
func (_c *MockAlertmanager_TestReceiver_Call) Run(run func(context1 context.Context, s string, v *alertmanagertypes.Receiver)) *MockAlertmanager_TestReceiver_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
@@ -1663,9 +1663,9 @@ func (_c *MockAlertmanager_TestReceiver_Call) Run(run func(context1 context.Cont
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(string)
|
||||
}
|
||||
var arg2 alertmanagertypes.Receiver
|
||||
var arg2 *alertmanagertypes.Receiver
|
||||
if args[2] != nil {
|
||||
arg2 = args[2].(alertmanagertypes.Receiver)
|
||||
arg2 = args[2].(*alertmanagertypes.Receiver)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
@@ -1681,7 +1681,7 @@ func (_c *MockAlertmanager_TestReceiver_Call) Return(err error) *MockAlertmanage
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockAlertmanager_TestReceiver_Call) RunAndReturn(run func(context1 context.Context, s string, v alertmanagertypes.Receiver) error) *MockAlertmanager_TestReceiver_Call {
|
||||
func (_c *MockAlertmanager_TestReceiver_Call) RunAndReturn(run func(context1 context.Context, s string, v *alertmanagertypes.Receiver) error) *MockAlertmanager_TestReceiver_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
@@ -1750,7 +1750,7 @@ func (_c *MockAlertmanager_UpdateAllRoutePoliciesByRuleId_Call) RunAndReturn(run
|
||||
}
|
||||
|
||||
// UpdateChannelByReceiverAndID provides a mock function for the type MockAlertmanager
|
||||
func (_mock *MockAlertmanager) UpdateChannelByReceiverAndID(context1 context.Context, s string, v alertmanagertypes.Receiver, uUID valuer.UUID) error {
|
||||
func (_mock *MockAlertmanager) UpdateChannelByReceiverAndID(context1 context.Context, s string, v *alertmanagertypes.Receiver, uUID valuer.UUID) error {
|
||||
ret := _mock.Called(context1, s, v, uUID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
@@ -1758,7 +1758,7 @@ func (_mock *MockAlertmanager) UpdateChannelByReceiverAndID(context1 context.Con
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, alertmanagertypes.Receiver, valuer.UUID) error); ok {
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, *alertmanagertypes.Receiver, valuer.UUID) error); ok {
|
||||
r0 = returnFunc(context1, s, v, uUID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
@@ -1774,13 +1774,13 @@ type MockAlertmanager_UpdateChannelByReceiverAndID_Call struct {
|
||||
// UpdateChannelByReceiverAndID is a helper method to define mock.On call
|
||||
// - context1 context.Context
|
||||
// - s string
|
||||
// - v alertmanagertypes.Receiver
|
||||
// - v *alertmanagertypes.Receiver
|
||||
// - uUID valuer.UUID
|
||||
func (_e *MockAlertmanager_Expecter) UpdateChannelByReceiverAndID(context1 interface{}, s interface{}, v interface{}, uUID interface{}) *MockAlertmanager_UpdateChannelByReceiverAndID_Call {
|
||||
return &MockAlertmanager_UpdateChannelByReceiverAndID_Call{Call: _e.mock.On("UpdateChannelByReceiverAndID", context1, s, v, uUID)}
|
||||
}
|
||||
|
||||
func (_c *MockAlertmanager_UpdateChannelByReceiverAndID_Call) Run(run func(context1 context.Context, s string, v alertmanagertypes.Receiver, uUID valuer.UUID)) *MockAlertmanager_UpdateChannelByReceiverAndID_Call {
|
||||
func (_c *MockAlertmanager_UpdateChannelByReceiverAndID_Call) Run(run func(context1 context.Context, s string, v *alertmanagertypes.Receiver, uUID valuer.UUID)) *MockAlertmanager_UpdateChannelByReceiverAndID_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
@@ -1790,9 +1790,9 @@ func (_c *MockAlertmanager_UpdateChannelByReceiverAndID_Call) Run(run func(conte
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(string)
|
||||
}
|
||||
var arg2 alertmanagertypes.Receiver
|
||||
var arg2 *alertmanagertypes.Receiver
|
||||
if args[2] != nil {
|
||||
arg2 = args[2].(alertmanagertypes.Receiver)
|
||||
arg2 = args[2].(*alertmanagertypes.Receiver)
|
||||
}
|
||||
var arg3 valuer.UUID
|
||||
if args[3] != nil {
|
||||
@@ -1813,7 +1813,7 @@ func (_c *MockAlertmanager_UpdateChannelByReceiverAndID_Call) Return(err error)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockAlertmanager_UpdateChannelByReceiverAndID_Call) RunAndReturn(run func(context1 context.Context, s string, v alertmanagertypes.Receiver, uUID valuer.UUID) error) *MockAlertmanager_UpdateChannelByReceiverAndID_Call {
|
||||
func (_c *MockAlertmanager_UpdateChannelByReceiverAndID_Call) RunAndReturn(run func(context1 context.Context, s string, v *alertmanagertypes.Receiver, uUID valuer.UUID) error) *MockAlertmanager_UpdateChannelByReceiverAndID_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ func (service *Service) PutAlerts(ctx context.Context, orgID string, alerts aler
|
||||
return server.PutAlerts(ctx, alerts)
|
||||
}
|
||||
|
||||
func (service *Service) TestReceiver(ctx context.Context, orgID string, receiver alertmanagertypes.Receiver) error {
|
||||
func (service *Service) TestReceiver(ctx context.Context, orgID string, receiver *alertmanagertypes.Receiver) error {
|
||||
service.serversMtx.RLock()
|
||||
defer service.serversMtx.RUnlock()
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ func (provider *provider) PutAlerts(ctx context.Context, orgID string, alerts al
|
||||
return provider.service.PutAlerts(ctx, orgID, alerts)
|
||||
}
|
||||
|
||||
func (provider *provider) TestReceiver(ctx context.Context, orgID string, receiver alertmanagertypes.Receiver) error {
|
||||
func (provider *provider) TestReceiver(ctx context.Context, orgID string, receiver *alertmanagertypes.Receiver) error {
|
||||
return provider.service.TestReceiver(ctx, orgID, receiver)
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ func (provider *provider) GetChannelByID(ctx context.Context, orgID string, chan
|
||||
return provider.configStore.GetChannelByID(ctx, orgID, channelID)
|
||||
}
|
||||
|
||||
func (provider *provider) UpdateChannelByReceiverAndID(ctx context.Context, orgID string, receiver alertmanagertypes.Receiver, id valuer.UUID) error {
|
||||
func (provider *provider) UpdateChannelByReceiverAndID(ctx context.Context, orgID string, receiver *alertmanagertypes.Receiver, id valuer.UUID) error {
|
||||
channel, err := provider.configStore.GetChannelByID(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -211,7 +211,7 @@ func (provider *provider) DeleteChannelByID(ctx context.Context, orgID string, c
|
||||
}))
|
||||
}
|
||||
|
||||
func (provider *provider) CreateChannel(ctx context.Context, orgID string, receiver alertmanagertypes.Receiver) (*alertmanagertypes.Channel, error) {
|
||||
func (provider *provider) CreateChannel(ctx context.Context, orgID string, receiver *alertmanagertypes.Receiver) (*alertmanagertypes.Channel, error) {
|
||||
config, err := provider.configStore.Get(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -192,26 +192,6 @@ func (provider *provider) addCloudIntegrationRoutes(router *mux.Router) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/cloud_integrations/{cloud_provider}/accounts/{id}/services/{service_id}", handler.New(
|
||||
provider.authzMiddleware.AdminAccess(provider.cloudIntegrationHandler.GetAccountService),
|
||||
handler.OpenAPIDef{
|
||||
ID: "GetAccountService",
|
||||
Tags: []string{"cloudintegration"},
|
||||
Summary: "Get service for account",
|
||||
Description: "This endpoint gets a service and its configuration for the specified cloud integration account",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(citypes.Service),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Agent check-in endpoint is kept same as older one to maintain backward compatibility with already deployed agents.
|
||||
// In the future, this endpoint will be deprecated and a new endpoint will be introduced for consistency with above endpoints.
|
||||
if err := router.Handle("/api/v1/cloud-integrations/{cloud_provider}/agent-check-in", handler.New(
|
||||
|
||||
@@ -76,7 +76,6 @@ type Handler interface {
|
||||
DisconnectAccount(http.ResponseWriter, *http.Request)
|
||||
ListServicesMetadata(http.ResponseWriter, *http.Request)
|
||||
GetService(http.ResponseWriter, *http.Request)
|
||||
GetAccountService(http.ResponseWriter, *http.Request)
|
||||
UpdateService(http.ResponseWriter, *http.Request)
|
||||
AgentCheckIn(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
@@ -322,51 +322,6 @@ func (handler *handler) GetService(rw http.ResponseWriter, r *http.Request) {
|
||||
render.Success(rw, http.StatusOK, svc)
|
||||
}
|
||||
|
||||
func (handler *handler) GetAccountService(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
provider, err := cloudintegrationtypes.NewCloudProvider(mux.Vars(r)["cloud_provider"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceID, err := cloudintegrationtypes.NewServiceID(provider, mux.Vars(r)["service_id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
cloudIntegrationID, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID := valuer.MustNewUUID(claims.OrgID)
|
||||
|
||||
_, err = handler.module.GetConnectedAccount(ctx, orgID, cloudIntegrationID, provider)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
svc, err := handler.module.GetService(ctx, orgID, serviceID, provider, cloudIntegrationID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, svc)
|
||||
}
|
||||
|
||||
func (handler *handler) UpdateService(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -149,11 +149,6 @@ func paginateWithBackfill(
|
||||
groupBy []qbtypes.GroupByKey,
|
||||
offset, limit int,
|
||||
) []map[string]string {
|
||||
|
||||
// note: we took a stand here that we are NOT removing those metricGroups from the array that are not in metadataMap.
|
||||
// we are relying on time adjustment logic from alignedMetricWindow. In future if a user complains about seeing metric groups
|
||||
// with missing metadata, we can consider removing those groups from the metricGroups array here before paginating.
|
||||
|
||||
metricKeySet := make(map[string]bool, len(metricGroups))
|
||||
for _, g := range metricGroups {
|
||||
metricKeySet[g.compositeKey] = true
|
||||
@@ -168,7 +163,7 @@ func paginateWithBackfill(
|
||||
sort.Strings(metadataOnlyKeys)
|
||||
|
||||
totalMetric := len(metricGroups)
|
||||
totalAll := len(metadataMap)
|
||||
totalAll := totalMetric + len(metadataOnlyKeys)
|
||||
|
||||
end := offset + limit
|
||||
if end > totalAll {
|
||||
@@ -312,57 +307,23 @@ func parseFullQueryResponse(
|
||||
return result
|
||||
}
|
||||
|
||||
// alignedMetricWindow returns step-floored time bounds and the metric tables
|
||||
// to use for the given window. The floor matches what the QB v5 metric
|
||||
// querier does internally (see querybuilder.AdjustedMetricTimeRange).
|
||||
// Please use the samplesAdjustedStartMs with samples table and tsAdjustedStartMs with ts tables.
|
||||
// Both can use the same flooredEndMs.
|
||||
func alignedMetricWindow(startMs, endMs int64) (
|
||||
uint64, // samplesAdjustedStartMs
|
||||
uint64, // flooredEndMs
|
||||
uint64, // tsAdjustedStartMs
|
||||
string, // distributedTSTable
|
||||
string, // localTSTable
|
||||
string, // distributedSamplesTable
|
||||
string, // localSamplesTable
|
||||
) {
|
||||
samplesAdjustedStartMs := uint64(startMs)
|
||||
flooredEndMs := uint64(endMs)
|
||||
stepSecs := querybuilder.RecommendedStepIntervalForMetric(samplesAdjustedStartMs, flooredEndMs)
|
||||
// note: this is the same flooring logic as in querybuilder.AdjustedMetricTimeRange. Duplicated code.
|
||||
// TODO(nikhilmantri0902): if the querybuilder.AdjustMetricTimeRange logic changes, this needs to be updated too.
|
||||
if stepSecs > 0 {
|
||||
samplesAdjustedStartMs = samplesAdjustedStartMs - (samplesAdjustedStartMs % (stepSecs * 1000))
|
||||
adjustStep := stepSecs
|
||||
if adjustStep > 60 {
|
||||
adjustStep = 60
|
||||
}
|
||||
flooredEndMs = flooredEndMs - (flooredEndMs % (adjustStep * 1000))
|
||||
}
|
||||
|
||||
tsAdjustedStartMs, _, distributedTSTable, localTSTable := telemetrymetrics.WhichTSTableToUse(
|
||||
samplesAdjustedStartMs, flooredEndMs, nil,
|
||||
)
|
||||
|
||||
distributedSamplesTable, localSamplesTable := telemetrymetrics.WhichSamplesTableToUse(
|
||||
samplesAdjustedStartMs, flooredEndMs,
|
||||
metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil,
|
||||
)
|
||||
|
||||
return samplesAdjustedStartMs, flooredEndMs, tsAdjustedStartMs, distributedTSTable, localTSTable, distributedSamplesTable, localSamplesTable
|
||||
}
|
||||
|
||||
// buildSamplesTblFingerprintSubQuery returns a SelectBuilder that selects distinct fingerprints
|
||||
// from the samples table for the given metric names and time range.
|
||||
// Bounds must already be step-floored by the caller via alignedMetricWindow.
|
||||
func (m *module) buildSamplesTblFingerprintSubQuery(metricNames []string, samplesTable string, flooredStart, flooredEnd uint64) *sqlbuilder.SelectBuilder {
|
||||
// from the samples table for the given metric names andtime range.
|
||||
func (m *module) buildSamplesTblFingerprintSubQuery(metricNames []string, startMs, endMs int64) *sqlbuilder.SelectBuilder {
|
||||
samplesTableName := telemetrymetrics.WhichSamplesTableToUse(
|
||||
uint64(startMs), uint64(endMs),
|
||||
metrictypes.UnspecifiedType,
|
||||
metrictypes.TimeAggregationUnspecified,
|
||||
nil,
|
||||
)
|
||||
localSamplesTable := strings.TrimPrefix(samplesTableName, "distributed_")
|
||||
fpSB := sqlbuilder.NewSelectBuilder()
|
||||
fpSB.Select("DISTINCT fingerprint")
|
||||
fpSB.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, samplesTable))
|
||||
fpSB.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, localSamplesTable))
|
||||
fpSB.Where(
|
||||
fpSB.In("metric_name", sqlbuilder.List(metricNames)),
|
||||
fpSB.GE("unix_milli", flooredStart),
|
||||
fpSB.L("unix_milli", flooredEnd),
|
||||
fpSB.GE("unix_milli", startMs),
|
||||
fpSB.L("unix_milli", endMs),
|
||||
)
|
||||
return fpSB
|
||||
}
|
||||
@@ -493,12 +454,12 @@ func (m *module) getMetadata(
|
||||
return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "groupBy must not be empty")
|
||||
}
|
||||
|
||||
// Step-floor the window and pick the right tables — matches the bounds the
|
||||
// QB v5 metric querier uses, so metadataMap covers the same universe the
|
||||
// ranking sees (see alignedMetricWindow doc).
|
||||
samplesStartMs, flooredEndMs, tsAdjustedStartMs, distributedTableName, _, _, localSamplesTable := alignedMetricWindow(startMs, endMs)
|
||||
// Pick the optimal timeseries table based on time range; also get adjusted start.
|
||||
adjustedStart, adjustedEnd, distributedTableName, _ := telemetrymetrics.WhichTSTableToUse(
|
||||
uint64(startMs), uint64(endMs), nil,
|
||||
)
|
||||
|
||||
fpSB := m.buildSamplesTblFingerprintSubQuery(metricNames, localSamplesTable, samplesStartMs, flooredEndMs)
|
||||
fpSB := m.buildSamplesTblFingerprintSubQuery(metricNames, startMs, endMs)
|
||||
|
||||
// Flatten groupBy keys to string names for SQL expressions and result scanning.
|
||||
groupByCols := make([]string, len(groupBy))
|
||||
@@ -533,8 +494,8 @@ func (m *module) getMetadata(
|
||||
innerSB.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, distributedTableName))
|
||||
innerSB.Where(
|
||||
innerSB.In("metric_name", sqlbuilder.List(metricNames)),
|
||||
innerSB.GE("unix_milli", tsAdjustedStartMs),
|
||||
innerSB.LE("unix_milli", flooredEndMs),
|
||||
innerSB.GE("unix_milli", adjustedStart),
|
||||
innerSB.L("unix_milli", adjustedEnd),
|
||||
fmt.Sprintf("fingerprint IN (%s)", innerSB.Var(fpSB)),
|
||||
)
|
||||
|
||||
|
||||
@@ -34,8 +34,9 @@ func (m *module) getPerGroupHostStatusCounts(
|
||||
pageGroupsFilterExpr := buildPageGroupsFilterExpr(pageGroups)
|
||||
filterExpr := mergeFilterExpressions(reqFilterExpr, pageGroupsFilterExpr)
|
||||
|
||||
// Step-floor bounds + resolve tables in one shot to match QB v5 querier.
|
||||
samplesStartMs, flooredEndMs, tsAdjustedStartMs, distributedTimeSeriesTableName, _, _, localSamplesTable := alignedMetricWindow(req.Start, req.End)
|
||||
adjustedStart, adjustedEnd, distributedTimeSeriesTableName, _ := telemetrymetrics.WhichTSTableToUse(
|
||||
uint64(req.Start), uint64(req.End), nil,
|
||||
)
|
||||
|
||||
hostNameExpr := fmt.Sprintf("JSONExtractString(labels, '%s')", inframonitoringtypes.HostNameAttrKey)
|
||||
|
||||
@@ -54,15 +55,15 @@ func (m *module) getPerGroupHostStatusCounts(
|
||||
)
|
||||
|
||||
// Build a fingerprint subquery to restrict to fingerprints with actual sample
|
||||
// data in the floored time range.
|
||||
fpSB := m.buildSamplesTblFingerprintSubQuery(metricNames, localSamplesTable, samplesStartMs, flooredEndMs)
|
||||
// data in the original time range (not the wider timeseries table window).
|
||||
fpSB := m.buildSamplesTblFingerprintSubQuery(metricNames, req.Start, req.End)
|
||||
|
||||
sb.Select(selectCols...)
|
||||
sb.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, distributedTimeSeriesTableName))
|
||||
sb.Where(
|
||||
sb.In("metric_name", sqlbuilder.List(metricNames)),
|
||||
sb.GE("unix_milli", tsAdjustedStartMs),
|
||||
sb.LE("unix_milli", flooredEndMs),
|
||||
sb.GE("unix_milli", adjustedStart),
|
||||
sb.L("unix_milli", adjustedEnd),
|
||||
fmt.Sprintf("fingerprint IN (%s)", sb.Var(fpSB)),
|
||||
)
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/querybuilder"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrymetrics"
|
||||
"github.com/SigNoz/signoz/pkg/types/inframonitoringtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/metrictypes"
|
||||
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/huandu/go-sqlbuilder"
|
||||
@@ -189,9 +190,15 @@ func (m *module) getPerGroupNodeConditionCounts(
|
||||
pageGroupsFilterExpr := buildPageGroupsFilterExpr(pageGroups)
|
||||
mergedFilterExpr := mergeFilterExpressions(userFilterExpr, pageGroupsFilterExpr)
|
||||
|
||||
// Step-floor bounds + resolve tables in one shot to match QB v5 querier.
|
||||
samplesStartMs, flooredEndMs, tsAdjustedStartMs, _, localTimeSeriesTable, distributedSamplesTable, _ := alignedMetricWindow(start, end)
|
||||
valueCol := telemetrymetrics.ValueColumnForSamplesTable(distributedSamplesTable)
|
||||
// Resolve tables. Same convention as pods.
|
||||
adjustedStart, adjustedEnd, _, localTimeSeriesTable := telemetrymetrics.WhichTSTableToUse(
|
||||
uint64(start), uint64(end), nil,
|
||||
)
|
||||
samplesTable := telemetrymetrics.WhichSamplesTableToUse(
|
||||
uint64(start), uint64(end),
|
||||
metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil,
|
||||
)
|
||||
valueCol := telemetrymetrics.ValueColumnForSamplesTable(samplesTable)
|
||||
|
||||
// ----- timeSeriesFPs -----
|
||||
timeSeriesFPs := sqlbuilder.NewSelectBuilder()
|
||||
@@ -208,8 +215,8 @@ func (m *module) getPerGroupNodeConditionCounts(
|
||||
timeSeriesFPs.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, localTimeSeriesTable))
|
||||
timeSeriesFPs.Where(
|
||||
timeSeriesFPs.E("metric_name", nodeConditionMetricName),
|
||||
timeSeriesFPs.GE("unix_milli", tsAdjustedStartMs),
|
||||
timeSeriesFPs.LE("unix_milli", flooredEndMs),
|
||||
timeSeriesFPs.GE("unix_milli", adjustedStart),
|
||||
timeSeriesFPs.L("unix_milli", adjustedEnd),
|
||||
)
|
||||
if mergedFilterExpr != "" {
|
||||
filterClause, err := m.buildFilterClause(ctx, &qbtypes.Filter{Expression: mergedFilterExpr}, start, end)
|
||||
@@ -242,12 +249,12 @@ func (m *module) getPerGroupNodeConditionCounts(
|
||||
latestConditionPerNode.Select(latestConditionPerNodeSelectCols...)
|
||||
latestConditionPerNode.From(fmt.Sprintf(
|
||||
"%s.%s AS samples INNER JOIN time_series_fps AS tsfp ON samples.fingerprint = tsfp.fingerprint",
|
||||
telemetrymetrics.DBName, distributedSamplesTable,
|
||||
telemetrymetrics.DBName, samplesTable,
|
||||
))
|
||||
latestConditionPerNode.Where(
|
||||
latestConditionPerNode.E("samples.metric_name", nodeConditionMetricName),
|
||||
latestConditionPerNode.GE("samples.unix_milli", samplesStartMs),
|
||||
latestConditionPerNode.L("samples.unix_milli", flooredEndMs),
|
||||
latestConditionPerNode.GE("samples.unix_milli", start),
|
||||
latestConditionPerNode.L("samples.unix_milli", end),
|
||||
"tsfp.node_name != ''",
|
||||
)
|
||||
latestConditionPerNode.GroupBy(latestConditionPerNodeGroupBy...)
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/querybuilder"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrymetrics"
|
||||
"github.com/SigNoz/signoz/pkg/types/inframonitoringtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/metrictypes"
|
||||
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/huandu/go-sqlbuilder"
|
||||
@@ -95,16 +96,14 @@ func buildPodRecords(
|
||||
}
|
||||
}
|
||||
|
||||
if attrs, ok := metadataMap[compositeKey]; ok {
|
||||
// podAge only makes sense when pod uid is in groupBy. Otherwise the
|
||||
// group can contain multiple pods with different start times.
|
||||
if isPodUIDInGroupBy {
|
||||
if startTimeStr, exists := attrs[podStartTimeAttrKey]; exists && startTimeStr != "" {
|
||||
if t, err := time.Parse(time.RFC3339, startTimeStr); err == nil {
|
||||
startTimeMs := t.UnixMilli()
|
||||
if startTimeMs > 0 {
|
||||
record.PodAge = reqEnd - startTimeMs
|
||||
}
|
||||
if attrs, ok := metadataMap[compositeKey]; ok && isPodUIDInGroupBy {
|
||||
// the condition above ensures we deduce age only if pod uid is in group by because if
|
||||
// it's not in group by then we might have multiple pod uids in the same group and hence then podAge wont make sense
|
||||
if startTimeStr, exists := attrs[podStartTimeAttrKey]; exists && startTimeStr != "" {
|
||||
if t, err := time.Parse(time.RFC3339, startTimeStr); err == nil {
|
||||
startTimeMs := t.UnixMilli()
|
||||
if startTimeMs > 0 {
|
||||
record.PodAge = reqEnd - startTimeMs
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,9 +209,15 @@ func (m *module) getPerGroupPodPhaseCounts(
|
||||
pageGroupsFilterExpr := buildPageGroupsFilterExpr(pageGroups)
|
||||
mergedFilterExpr := mergeFilterExpressions(userFilterExpr, pageGroupsFilterExpr)
|
||||
|
||||
// Step-floor bounds + resolve tables in one shot to match QB v5 querier.
|
||||
samplesStartMs, flooredEndMs, tsAdjustedStart, _, localTimeSeriesTable, distributedSamplesTable, _ := alignedMetricWindow(start, end)
|
||||
valueCol := telemetrymetrics.ValueColumnForSamplesTable(distributedSamplesTable)
|
||||
// Resolve tables. Same convention as hosts (distributed names from helpers).
|
||||
adjustedStart, adjustedEnd, _, localTimeSeriesTable := telemetrymetrics.WhichTSTableToUse(
|
||||
uint64(start), uint64(end), nil,
|
||||
)
|
||||
samplesTable := telemetrymetrics.WhichSamplesTableToUse(
|
||||
uint64(start), uint64(end),
|
||||
metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil,
|
||||
)
|
||||
valueCol := telemetrymetrics.ValueColumnForSamplesTable(samplesTable)
|
||||
|
||||
// ----- timeSeriesFPs -----
|
||||
timeSeriesFPs := sqlbuilder.NewSelectBuilder()
|
||||
@@ -229,8 +234,8 @@ func (m *module) getPerGroupPodPhaseCounts(
|
||||
timeSeriesFPs.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, localTimeSeriesTable))
|
||||
timeSeriesFPs.Where(
|
||||
timeSeriesFPs.E("metric_name", podPhaseMetricName),
|
||||
timeSeriesFPs.GE("unix_milli", tsAdjustedStart),
|
||||
timeSeriesFPs.LE("unix_milli", flooredEndMs),
|
||||
timeSeriesFPs.GE("unix_milli", adjustedStart),
|
||||
timeSeriesFPs.L("unix_milli", adjustedEnd),
|
||||
)
|
||||
if mergedFilterExpr != "" {
|
||||
filterClause, err := m.buildFilterClause(ctx, &qbtypes.Filter{Expression: mergedFilterExpr}, start, end)
|
||||
@@ -262,12 +267,12 @@ func (m *module) getPerGroupPodPhaseCounts(
|
||||
latestPhasePerPod.Select(latestPhasePerPodSelectCols...)
|
||||
latestPhasePerPod.From(fmt.Sprintf(
|
||||
"%s.%s AS samples INNER JOIN time_series_fps AS tsfp ON samples.fingerprint = tsfp.fingerprint",
|
||||
telemetrymetrics.DBName, distributedSamplesTable,
|
||||
telemetrymetrics.DBName, samplesTable,
|
||||
))
|
||||
latestPhasePerPod.Where(
|
||||
latestPhasePerPod.E("samples.metric_name", podPhaseMetricName),
|
||||
latestPhasePerPod.GE("samples.unix_milli", samplesStartMs),
|
||||
latestPhasePerPod.L("samples.unix_milli", flooredEndMs),
|
||||
latestPhasePerPod.GE("samples.unix_milli", start),
|
||||
latestPhasePerPod.L("samples.unix_milli", end),
|
||||
"tsfp.pod_uid != ''",
|
||||
)
|
||||
latestPhasePerPod.GroupBy(latestPhasePerPodGroupBy...)
|
||||
|
||||
@@ -981,7 +981,7 @@ func (m *module) fetchMetricsStatsWithSamples(
|
||||
ctx = m.withMetricsExplorerContext(ctx, "fetchMetricsStatsWithSamples")
|
||||
|
||||
start, end, distributedTsTable, localTsTable := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), nil)
|
||||
samplesTable, _ := telemetrymetrics.WhichSamplesTableToUse(uint64(req.Start), uint64(req.End), metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil)
|
||||
samplesTable := telemetrymetrics.WhichSamplesTableToUse(uint64(req.Start), uint64(req.End), metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil)
|
||||
countExp := telemetrymetrics.CountExpressionForSamplesTable(samplesTable)
|
||||
|
||||
// Timeseries counts per metric
|
||||
@@ -1155,7 +1155,7 @@ func (m *module) computeSamplesTreemap(ctx context.Context, req *metricsexplorer
|
||||
ctx = m.withMetricsExplorerContext(ctx, "computeSamplesTreemap")
|
||||
|
||||
start, end, distributedTsTable, localTsTable := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), nil)
|
||||
samplesTable, _ := telemetrymetrics.WhichSamplesTableToUse(uint64(req.Start), uint64(req.End), metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil)
|
||||
samplesTable := telemetrymetrics.WhichSamplesTableToUse(uint64(req.Start), uint64(req.End), metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil)
|
||||
countExp := telemetrymetrics.CountExpressionForSamplesTable(samplesTable)
|
||||
|
||||
candidateLimit := req.Limit + 50
|
||||
|
||||
@@ -269,7 +269,7 @@ func (migration *addAlertmanager) msTeamsChannelToMSTeamsV2Channel(c *alertmanag
|
||||
return nil
|
||||
}
|
||||
|
||||
func (migration *addAlertmanager) msTeamsReceiverToMSTeamsV2Receiver(receiver alertmanagertypes.Receiver) alertmanagertypes.Receiver {
|
||||
func (migration *addAlertmanager) msTeamsReceiverToMSTeamsV2Receiver(receiver *alertmanagertypes.Receiver) *alertmanagertypes.Receiver {
|
||||
if receiver.MSTeamsConfigs == nil {
|
||||
return receiver
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggDeltaFastPath(
|
||||
|
||||
sb.SelectMore(fmt.Sprintf("%s AS value", aggCol))
|
||||
|
||||
tbl, _ := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
|
||||
tbl := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
|
||||
sb.From(fmt.Sprintf("%s.%s AS points", DBName, tbl))
|
||||
sb.JoinWithOption(sqlbuilder.InnerJoin, timeSeriesCTE, "points.fingerprint = filtered_time_series.fingerprint")
|
||||
sb.Where(
|
||||
@@ -369,7 +369,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggDelta(
|
||||
|
||||
sb.SelectMore(fmt.Sprintf("%s AS per_series_value", aggCol))
|
||||
|
||||
tbl, _ := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
|
||||
tbl := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
|
||||
sb.From(fmt.Sprintf("%s.%s AS points", DBName, tbl))
|
||||
sb.JoinWithOption(sqlbuilder.InnerJoin, timeSeriesCTE, "points.fingerprint = filtered_time_series.fingerprint")
|
||||
sb.Where(
|
||||
@@ -410,7 +410,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggCumulativeOrUnspecified(
|
||||
}
|
||||
baseSb.SelectMore(fmt.Sprintf("%s AS per_series_value", aggCol))
|
||||
|
||||
tbl, _ := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
|
||||
tbl := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
|
||||
baseSb.From(fmt.Sprintf("%s.%s AS points", DBName, tbl))
|
||||
baseSb.JoinWithOption(sqlbuilder.InnerJoin, timeSeriesCTE, "points.fingerprint = filtered_time_series.fingerprint")
|
||||
baseSb.Where(
|
||||
@@ -501,7 +501,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggForMultipleTemporalities(
|
||||
sb.SelectMore(expr)
|
||||
}
|
||||
|
||||
tbl, _ := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
|
||||
tbl := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
|
||||
sb.From(fmt.Sprintf("%s.%s AS points", DBName, tbl))
|
||||
sb.JoinWithOption(sqlbuilder.InnerJoin, timeSeriesCTE, "points.fingerprint = filtered_time_series.fingerprint")
|
||||
sb.Where(
|
||||
|
||||
@@ -135,56 +135,44 @@ func ValueColumnForSamplesTable(tableName string) string {
|
||||
return "value"
|
||||
}
|
||||
|
||||
// WhichSamplesTableToUse returns the distributed and local samples table names
|
||||
// (in that order) appropriate for the given window, metric type, and time aggregation.
|
||||
//
|
||||
// start and end are in milliseconds. We have three tables for samples:
|
||||
// 1. distributed_samples_v4
|
||||
// 2. distributed_samples_v4_agg_5m — for queries with time range >= 1 day and < 1 week
|
||||
// 3. distributed_samples_v4_agg_30m — for queries with time range >= 1 week
|
||||
//
|
||||
// If the `timeAggregation` is `count_distinct` we can't use the aggregated tables
|
||||
// because they don't support it.
|
||||
// start and end are in milliseconds
|
||||
// we have three tables for samples
|
||||
// 1. distributed_samples_v4
|
||||
// 2. distributed_samples_v4_agg_5m - for queries with time range above or equal to 1 day and less than 1 week
|
||||
// 3. distributed_samples_v4_agg_30m - for queries with time range above or equal to 1 week
|
||||
// if the `timeAggregation` is `count_distinct` we can't use the aggregated tables because they don't support it.
|
||||
func WhichSamplesTableToUse(
|
||||
start, end uint64,
|
||||
metricType metrictypes.Type,
|
||||
timeAggregation metrictypes.TimeAggregation,
|
||||
tableHints *metrictypes.MetricTableHints,
|
||||
) (string, string) {
|
||||
) string {
|
||||
// if we have a hint for the table, we need to use it
|
||||
// the hint will be used to override the default table selection logic.
|
||||
// SamplesTableName is the distributed name; derive the local via switch.
|
||||
if tableHints != nil && tableHints.SamplesTableName != "" {
|
||||
switch tableHints.SamplesTableName {
|
||||
case SamplesV4TableName:
|
||||
return SamplesV4TableName, SamplesV4LocalTableName
|
||||
case SamplesV4Agg5mTableName:
|
||||
return SamplesV4Agg5mTableName, SamplesV4Agg5mLocalTableName
|
||||
case SamplesV4Agg30mTableName:
|
||||
return SamplesV4Agg30mTableName, SamplesV4Agg30mLocalTableName
|
||||
case ExpHistogramTableName:
|
||||
return ExpHistogramTableName, ExpHistogramLocalTableName
|
||||
// the hint will be used to override the default table selection logic
|
||||
if tableHints != nil {
|
||||
if tableHints.SamplesTableName != "" {
|
||||
return tableHints.SamplesTableName
|
||||
}
|
||||
return tableHints.SamplesTableName, tableHints.SamplesTableName
|
||||
}
|
||||
|
||||
// we don't have any aggregated table for sketches (yet)
|
||||
if metricType == metrictypes.ExpHistogramType {
|
||||
return ExpHistogramTableName, ExpHistogramLocalTableName
|
||||
return ExpHistogramLocalTableName
|
||||
}
|
||||
|
||||
// if the time aggregation is count_distinct, we need to use the distributed_samples_v4 table
|
||||
// because the aggregated tables don't support count_distinct
|
||||
if timeAggregation == metrictypes.TimeAggregationCountDistinct {
|
||||
return SamplesV4TableName, SamplesV4LocalTableName
|
||||
return SamplesV4TableName
|
||||
}
|
||||
|
||||
if end-start < oneDayInMilliseconds+offsetBucket {
|
||||
return SamplesV4TableName, SamplesV4LocalTableName
|
||||
return SamplesV4TableName
|
||||
} else if end-start < oneWeekInMilliseconds+offsetBucket {
|
||||
return SamplesV4Agg5mTableName, SamplesV4Agg5mLocalTableName
|
||||
return SamplesV4Agg5mTableName
|
||||
} else {
|
||||
return SamplesV4Agg30mTableName
|
||||
}
|
||||
return SamplesV4Agg30mTableName, SamplesV4Agg30mLocalTableName
|
||||
}
|
||||
|
||||
func AggregationColumnForSamplesTable(
|
||||
@@ -194,7 +182,7 @@ func AggregationColumnForSamplesTable(
|
||||
timeAggregation metrictypes.TimeAggregation,
|
||||
tableHints *metrictypes.MetricTableHints,
|
||||
) (string, error) {
|
||||
tableName, _ := WhichSamplesTableToUse(start, end, metricType, timeAggregation, tableHints)
|
||||
tableName := WhichSamplesTableToUse(start, end, metricType, timeAggregation, tableHints)
|
||||
var aggregationColumn string
|
||||
switch temporality {
|
||||
case metrictypes.Delta:
|
||||
|
||||
@@ -134,7 +134,7 @@ func NewAlertsFromPostableAlerts(ctx context.Context, postableAlerts PostableAle
|
||||
return validAlerts, errs
|
||||
}
|
||||
|
||||
func NewTestAlert(receiver Receiver, startsAt time.Time, updatedAt time.Time) *Alert {
|
||||
func NewTestAlert(receiver *Receiver, startsAt time.Time, updatedAt time.Time) *Alert {
|
||||
return &Alert{
|
||||
Alert: model.Alert{
|
||||
StartsAt: startsAt,
|
||||
|
||||
@@ -56,7 +56,7 @@ type Channel struct {
|
||||
|
||||
// NewChannelFromReceiver creates a new Channel from a Receiver.
|
||||
// It can return nil if the receiver is the default receiver.
|
||||
func NewChannelFromReceiver(receiver config.Receiver, orgID string) (*Channel, error) {
|
||||
func NewChannelFromReceiver(receiver *Receiver, orgID string) (*Channel, error) {
|
||||
if receiver.Name == DefaultReceiverName {
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, ErrCodeAlertmanagerChannelInvalid, "cannot use %s name as a channel name", receiver.Name)
|
||||
}
|
||||
@@ -74,46 +74,13 @@ func NewChannelFromReceiver(receiver config.Receiver, orgID string) (*Channel, e
|
||||
OrgID: orgID,
|
||||
}
|
||||
|
||||
// Use reflection to examine receiver struct fields
|
||||
receiverType := reflect.TypeOf(receiver)
|
||||
receiverVal := reflect.ValueOf(receiver)
|
||||
|
||||
// Iterate through fields looking for *Config fields
|
||||
for i := 0; i < receiverType.NumField(); i++ {
|
||||
field := receiverType.Field(i)
|
||||
fieldVal := receiverVal.Field(i)
|
||||
|
||||
// Skip if not a slice or is empty
|
||||
if fieldVal.Kind() != reflect.Slice || fieldVal.Len() == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get channel type from yaml tag
|
||||
yamlTag := field.Tag.Get("yaml")
|
||||
if yamlTag == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Extract the base type name (e.g., "email_configs" -> "email")
|
||||
matches := receiverTypeRegex.FindStringSubmatch(yamlTag)
|
||||
if len(matches) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
channelType := matches[1]
|
||||
|
||||
// Marshal config data to JSON
|
||||
configData, err := json.Marshal(receiver)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
channel.Type = channelType
|
||||
channel.Data = string(configData)
|
||||
break
|
||||
data, err := json.Marshal(receiver)
|
||||
if err != nil {
|
||||
return nil, errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "marshal receiver")
|
||||
}
|
||||
channel.Data = string(data)
|
||||
|
||||
// If we were unable to find the channel type, return an error
|
||||
channel.Type = receiverChannelType(receiver)
|
||||
if channel.Type == "" {
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, ErrCodeAlertmanagerChannelInvalid, "channel '%s' must have at least one notification configuration (e.g., email_configs, webhook_configs, slack_configs)", receiver.Name)
|
||||
}
|
||||
@@ -121,6 +88,44 @@ func NewChannelFromReceiver(receiver config.Receiver, orgID string) (*Channel, e
|
||||
return &channel, nil
|
||||
}
|
||||
|
||||
// receiverChannelType returns the channel.Type discriminator. Walks
|
||||
// Receiver's own fields first (native), then the embed (upstream); first
|
||||
// non-empty *_configs slice wins.
|
||||
func receiverChannelType(receiver *Receiver) string {
|
||||
if t := nonEmptyConfigsField(reflect.ValueOf(*receiver)); t != "" {
|
||||
return t
|
||||
}
|
||||
if t := nonEmptyConfigsField(reflect.ValueOf(*receiver.Receiver)); t != "" {
|
||||
return t
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func nonEmptyConfigsField(v reflect.Value) string {
|
||||
t := v.Type()
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
fieldVal := v.Field(i)
|
||||
|
||||
if fieldVal.Kind() != reflect.Slice || fieldVal.Len() == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
yamlTag := field.Tag.Get("yaml")
|
||||
if yamlTag == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Extract the base type name (e.g., "email_configs" -> "email").
|
||||
matches := receiverTypeRegex.FindStringSubmatch(yamlTag)
|
||||
if len(matches) != 2 {
|
||||
continue
|
||||
}
|
||||
return matches[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func NewConfigFromChannels(globalConfig GlobalConfig, routeConfig RouteConfig, channels Channels, orgID string) (*Config, error) {
|
||||
cfg, err := NewDefaultConfig(
|
||||
globalConfig,
|
||||
@@ -182,7 +187,7 @@ func NewStatsFromChannels(channels Channels) map[string]any {
|
||||
return stats
|
||||
}
|
||||
|
||||
func (c *Channel) Update(receiver Receiver) error {
|
||||
func (c *Channel) Update(receiver *Receiver) error {
|
||||
channel, err := NewChannelFromReceiver(receiver, c.OrgID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -192,6 +197,7 @@ func (c *Channel) Update(receiver Receiver) error {
|
||||
return errors.Newf(errors.TypeInvalidInput, ErrCodeAlertmanagerChannelNameMismatch, "cannot update channel name")
|
||||
}
|
||||
|
||||
c.Type = channel.Type
|
||||
c.Data = channel.Data
|
||||
c.UpdatedAt = time.Now()
|
||||
|
||||
@@ -210,15 +216,19 @@ func (PostableChannel) JSONSchema() (jsonschema.Schema, error) {
|
||||
schema.WithRequired("name")
|
||||
|
||||
var oneOf []jsonschema.SchemaOrBool
|
||||
receiverType := reflect.TypeOf(Receiver{})
|
||||
for i := 0; i < receiverType.NumField(); i++ {
|
||||
jsonTag := strings.Split(receiverType.Field(i).Tag.Get("json"), ",")[0]
|
||||
if !strings.HasSuffix(jsonTag, "_configs") {
|
||||
continue
|
||||
// Walk both halves: native fields on Receiver, upstream on the embed.
|
||||
collect := func(t reflect.Type) {
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
jsonTag := strings.Split(t.Field(i).Tag.Get("json"), ",")[0]
|
||||
if !strings.HasSuffix(jsonTag, "_configs") {
|
||||
continue
|
||||
}
|
||||
branch := (&jsonschema.Schema{}).WithRequired(jsonTag)
|
||||
oneOf = append(oneOf, branch.ToSchemaOrBool())
|
||||
}
|
||||
branch := (&jsonschema.Schema{}).WithRequired(jsonTag)
|
||||
oneOf = append(oneOf, branch.ToSchemaOrBool())
|
||||
}
|
||||
collect(reflect.TypeOf(Receiver{}))
|
||||
collect(reflect.TypeOf(config.Receiver{}))
|
||||
|
||||
schema.WithOneOf(oneOf...)
|
||||
|
||||
|
||||
@@ -285,7 +285,8 @@ func TestNewChannelFromReceiver(t *testing.T) {
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
channel, err := NewChannelFromReceiver(testCase.receiver, "1")
|
||||
receiver := testCase.receiver
|
||||
channel, err := NewChannelFromReceiver(&Receiver{Receiver: &receiver}, "1")
|
||||
if !testCase.pass {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
@@ -299,3 +300,31 @@ func TestNewChannelFromReceiver(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Type and Data are derived from the native googlechat_configs field.
|
||||
func TestNewChannelFromReceiverGoogleChat(t *testing.T) {
|
||||
webhookURL, err := url.Parse("https://chat.googleapis.com/v1/spaces/test/messages")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
receiver := &Receiver{
|
||||
Receiver: &config.Receiver{Name: "googlechat-receiver"},
|
||||
GoogleChatConfigs: []*GoogleChatReceiverConfig{
|
||||
{
|
||||
WebhookURL: &config.SecretURL{URL: webhookURL},
|
||||
Title: "Alert",
|
||||
Text: "Body",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
channel, err := NewChannelFromReceiver(receiver, "1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "googlechat-receiver", channel.Name)
|
||||
assert.Equal(t, "googlechat", channel.Type)
|
||||
assert.JSONEq(t,
|
||||
`{"name":"googlechat-receiver","googlechat_configs":[{"send_resolved":false,"webhook_url":"https://chat.googleapis.com/v1/spaces/test/messages","title":"Alert","text":"Body"}]}`,
|
||||
channel.Data,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -59,12 +59,43 @@ type Config struct {
|
||||
|
||||
// storeableConfig is the representation of the config in the store
|
||||
storeableConfig *StoreableConfig
|
||||
|
||||
// customConfigs holds the custom notifier configs upstream's
|
||||
// config.Receiver cannot carry, keyed by receiver name.
|
||||
customConfigs map[string]customReceiverConfigs
|
||||
}
|
||||
|
||||
// customReceiverConfigs is the per-receiver custom notifier
|
||||
// configs. To add another, mirror GoogleChat: a field here, a matching field
|
||||
// on Receiver, and extensions to customConfigsOf + isEmpty.
|
||||
type customReceiverConfigs struct {
|
||||
GoogleChat []*GoogleChatReceiverConfig
|
||||
}
|
||||
|
||||
func (c customReceiverConfigs) isEmpty() bool {
|
||||
return len(c.GoogleChat) == 0
|
||||
}
|
||||
|
||||
func customConfigsOf(receiver *Receiver) customReceiverConfigs {
|
||||
return customReceiverConfigs{
|
||||
GoogleChat: receiver.GoogleChatConfigs,
|
||||
}
|
||||
}
|
||||
|
||||
// storedConfig is the persistence unit. The outer Receivers shadows the
|
||||
// embed's so receivers emit as the extended *Receiver (encoding/json:
|
||||
// shallower-field-wins on duplicate JSON names).
|
||||
type storedConfig struct {
|
||||
*config.Config
|
||||
Receivers []*Receiver `json:"receivers"`
|
||||
}
|
||||
|
||||
func NewConfig(c *config.Config, orgID string) *Config {
|
||||
raw := string(newRawFromConfig(c))
|
||||
customConfigs := make(map[string]customReceiverConfigs)
|
||||
raw := string(newRawFromConfig(c, customConfigs))
|
||||
return &Config{
|
||||
alertmanagerConfig: c,
|
||||
customConfigs: customConfigs,
|
||||
storeableConfig: &StoreableConfig{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: valuer.GenerateUUID(),
|
||||
@@ -81,13 +112,14 @@ func NewConfig(c *config.Config, orgID string) *Config {
|
||||
}
|
||||
|
||||
func NewConfigFromStoreableConfig(sc *StoreableConfig) (*Config, error) {
|
||||
alertmanagerConfig, err := newConfigFromString(sc.Config)
|
||||
alertmanagerConfig, customConfigs, err := newConfigFromString(sc.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Config{
|
||||
alertmanagerConfig: alertmanagerConfig,
|
||||
customConfigs: customConfigs,
|
||||
storeableConfig: sc,
|
||||
}, nil
|
||||
}
|
||||
@@ -113,32 +145,47 @@ func NewDefaultConfig(globalConfig GlobalConfig, routeConfig RouteConfig, orgID
|
||||
}, orgID), nil
|
||||
}
|
||||
|
||||
func newConfigFromString(s string) (*config.Config, error) {
|
||||
config := new(config.Config)
|
||||
err := json.Unmarshal([]byte(s), config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func newConfigFromString(s string) (*config.Config, map[string]customReceiverConfigs, error) {
|
||||
stored := storedConfig{Config: new(config.Config)}
|
||||
if err := json.Unmarshal([]byte(s), &stored); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for i, receiver := range config.Receivers {
|
||||
bytes, err := json.Marshal(receiver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
amConfig := stored.Config
|
||||
amConfig.Receivers = make([]config.Receiver, len(stored.Receivers))
|
||||
customConfigs := make(map[string]customReceiverConfigs)
|
||||
|
||||
receiver, err := NewReceiver(string(bytes))
|
||||
// Re-run NewReceiver per receiver so defaults apply (mirrors create path).
|
||||
for i, rcv := range stored.Receivers {
|
||||
rcvJSON, err := json.Marshal(rcv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
parsed, err := NewReceiver(string(rcvJSON))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
amConfig.Receivers[i] = *parsed.Receiver
|
||||
if custom := customConfigsOf(parsed); !custom.isEmpty() {
|
||||
customConfigs[parsed.Name] = custom
|
||||
}
|
||||
|
||||
config.Receivers[i] = receiver
|
||||
}
|
||||
|
||||
return config, nil
|
||||
return amConfig, customConfigs, nil
|
||||
}
|
||||
|
||||
func newRawFromConfig(c *config.Config) []byte {
|
||||
b, err := json.Marshal(c)
|
||||
func newRawFromConfig(c *config.Config, customConfigs map[string]customReceiverConfigs) []byte {
|
||||
receivers := make([]*Receiver, len(c.Receivers))
|
||||
for i := range c.Receivers {
|
||||
base := c.Receivers[i]
|
||||
custom := customConfigs[base.Name]
|
||||
receivers[i] = &Receiver{
|
||||
Receiver: &base,
|
||||
GoogleChatConfigs: custom.GoogleChat,
|
||||
}
|
||||
}
|
||||
|
||||
b, err := json.Marshal(storedConfig{Config: c, Receivers: receivers})
|
||||
if err != nil {
|
||||
// Taking inspiration from the upstream. This is never expected to happen.
|
||||
return []byte(fmt.Sprintf("<error creating config string: %s>", err))
|
||||
@@ -151,6 +198,14 @@ func newConfigHash(s string) [16]byte {
|
||||
return md5.Sum([]byte(s))
|
||||
}
|
||||
|
||||
// flush refreshes the storeable representation. Call after any mutation.
|
||||
func (c *Config) flush() {
|
||||
raw := string(newRawFromConfig(c.alertmanagerConfig, c.customConfigs))
|
||||
c.storeableConfig.Config = raw
|
||||
c.storeableConfig.Hash = fmt.Sprintf("%x", newConfigHash(raw))
|
||||
c.storeableConfig.UpdatedAt = time.Now()
|
||||
}
|
||||
|
||||
func (c *Config) CopyWithReset() (*Config, error) {
|
||||
newConfig, err := NewDefaultConfig(
|
||||
*c.alertmanagerConfig.Global,
|
||||
@@ -179,9 +234,7 @@ func (c *Config) SetGlobalConfig(globalConfig GlobalConfig) error {
|
||||
globalConfig.SMTPRequireTLS = smtpRequireTLS
|
||||
|
||||
c.alertmanagerConfig.Global = &globalConfig
|
||||
c.storeableConfig.Config = string(newRawFromConfig(c.alertmanagerConfig))
|
||||
c.storeableConfig.Hash = fmt.Sprintf("%x", newConfigHash(c.storeableConfig.Config))
|
||||
c.storeableConfig.UpdatedAt = time.Now()
|
||||
c.flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -193,9 +246,7 @@ func (c *Config) SetRouteConfig(routeConfig RouteConfig) error {
|
||||
}
|
||||
c.alertmanagerConfig.Route = route
|
||||
|
||||
c.storeableConfig.Config = string(newRawFromConfig(c.alertmanagerConfig))
|
||||
c.storeableConfig.Hash = fmt.Sprintf("%x", newConfigHash(c.storeableConfig.Config))
|
||||
c.storeableConfig.UpdatedAt = time.Now()
|
||||
c.flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -207,9 +258,7 @@ func (c *Config) AddInhibitRules(rules []config.InhibitRule) error {
|
||||
|
||||
c.alertmanagerConfig.InhibitRules = append(c.alertmanagerConfig.InhibitRules, rules...)
|
||||
|
||||
c.storeableConfig.Config = string(newRawFromConfig(c.alertmanagerConfig))
|
||||
c.storeableConfig.Hash = fmt.Sprintf("%x", newConfigHash(c.storeableConfig.Config))
|
||||
c.storeableConfig.UpdatedAt = time.Now()
|
||||
c.flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -222,7 +271,7 @@ func (c *Config) StoreableConfig() *StoreableConfig {
|
||||
return c.storeableConfig
|
||||
}
|
||||
|
||||
func (c *Config) CreateReceiver(receiver config.Receiver) error {
|
||||
func (c *Config) CreateReceiver(receiver *Receiver) error {
|
||||
// check that receiver name is not already used
|
||||
for _, existingReceiver := range c.alertmanagerConfig.Receivers {
|
||||
if existingReceiver.Name == receiver.Name {
|
||||
@@ -236,33 +285,39 @@ func (c *Config) CreateReceiver(receiver config.Receiver) error {
|
||||
}
|
||||
|
||||
c.alertmanagerConfig.Route.Routes = append(c.alertmanagerConfig.Route.Routes, route)
|
||||
c.alertmanagerConfig.Receivers = append(c.alertmanagerConfig.Receivers, receiver)
|
||||
c.alertmanagerConfig.Receivers = append(c.alertmanagerConfig.Receivers, *receiver.Receiver)
|
||||
c.setCustomConfigs(receiver)
|
||||
|
||||
if err := c.alertmanagerConfig.UnmarshalYAML(func(i interface{}) error { return nil }); err != nil {
|
||||
return err
|
||||
}
|
||||
c.applyNativeDefaults()
|
||||
|
||||
c.storeableConfig.Config = string(newRawFromConfig(c.alertmanagerConfig))
|
||||
c.storeableConfig.Hash = fmt.Sprintf("%x", newConfigHash(c.storeableConfig.Config))
|
||||
c.storeableConfig.UpdatedAt = time.Now()
|
||||
c.flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) GetReceiver(name string) (Receiver, error) {
|
||||
for _, receiver := range c.alertmanagerConfig.Receivers {
|
||||
if receiver.Name == name {
|
||||
return receiver, nil
|
||||
func (c *Config) GetReceiver(name string) (*Receiver, error) {
|
||||
for i := range c.alertmanagerConfig.Receivers {
|
||||
if c.alertmanagerConfig.Receivers[i].Name == name {
|
||||
base := c.alertmanagerConfig.Receivers[i]
|
||||
custom := c.customConfigs[name]
|
||||
return &Receiver{
|
||||
Receiver: &base,
|
||||
GoogleChatConfigs: custom.GoogleChat,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return Receiver{}, errors.Newf(errors.TypeNotFound, ErrCodeAlertmanagerChannelNotFound, "channel with name %q not found", name)
|
||||
return nil, errors.Newf(errors.TypeNotFound, ErrCodeAlertmanagerChannelNotFound, "channel with name %q not found", name)
|
||||
}
|
||||
|
||||
func (c *Config) UpdateReceiver(receiver config.Receiver) error {
|
||||
func (c *Config) UpdateReceiver(receiver *Receiver) error {
|
||||
// find and update receiver
|
||||
for i, existingReceiver := range c.alertmanagerConfig.Receivers {
|
||||
if existingReceiver.Name == receiver.Name {
|
||||
c.alertmanagerConfig.Receivers[i] = receiver
|
||||
c.alertmanagerConfig.Receivers[i] = *receiver.Receiver
|
||||
c.setCustomConfigs(receiver)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -270,10 +325,9 @@ func (c *Config) UpdateReceiver(receiver config.Receiver) error {
|
||||
if err := c.alertmanagerConfig.UnmarshalYAML(func(i interface{}) error { return nil }); err != nil {
|
||||
return err
|
||||
}
|
||||
c.applyNativeDefaults()
|
||||
|
||||
c.storeableConfig.Config = string(newRawFromConfig(c.alertmanagerConfig))
|
||||
c.storeableConfig.Hash = fmt.Sprintf("%x", newConfigHash(c.storeableConfig.Config))
|
||||
c.storeableConfig.UpdatedAt = time.Now()
|
||||
c.flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -298,13 +352,36 @@ func (c *Config) DeleteReceiver(name string) error {
|
||||
}
|
||||
}
|
||||
|
||||
c.storeableConfig.Config = string(newRawFromConfig(c.alertmanagerConfig))
|
||||
c.storeableConfig.Hash = fmt.Sprintf("%x", newConfigHash(c.storeableConfig.Config))
|
||||
c.storeableConfig.UpdatedAt = time.Now()
|
||||
delete(c.customConfigs, name)
|
||||
|
||||
c.flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) setCustomConfigs(receiver *Receiver) {
|
||||
if custom := customConfigsOf(receiver); !custom.isEmpty() {
|
||||
c.customConfigs[receiver.Name] = custom
|
||||
} else {
|
||||
delete(c.customConfigs, receiver.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) applyNativeDefaults() {
|
||||
if c.alertmanagerConfig.Global == nil {
|
||||
return
|
||||
}
|
||||
httpDefault := c.alertmanagerConfig.Global.HTTPConfig
|
||||
|
||||
for _, custom := range c.customConfigs {
|
||||
for _, gc := range custom.GoogleChat {
|
||||
if gc.HTTPConfig == nil {
|
||||
gc.HTTPConfig = httpDefault
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) CreateRuleIDMatcher(ruleID string, receiverNames []string) error {
|
||||
if c.alertmanagerConfig.Route == nil {
|
||||
return errors.New(errors.TypeInvalidInput, ErrCodeAlertmanagerConfigInvalid, "route is nil")
|
||||
@@ -318,9 +395,7 @@ func (c *Config) CreateRuleIDMatcher(ruleID string, receiverNames []string) erro
|
||||
}
|
||||
}
|
||||
|
||||
c.storeableConfig.Config = string(newRawFromConfig(c.alertmanagerConfig))
|
||||
c.storeableConfig.Hash = fmt.Sprintf("%x", newConfigHash(c.storeableConfig.Config))
|
||||
c.storeableConfig.UpdatedAt = time.Now()
|
||||
c.flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -339,9 +414,7 @@ func (c *Config) DeleteRuleIDInhibitor(ruleID string) error {
|
||||
}
|
||||
}
|
||||
c.alertmanagerConfig.InhibitRules = filteredRules
|
||||
c.storeableConfig.Config = string(newRawFromConfig(c.alertmanagerConfig))
|
||||
c.storeableConfig.Hash = fmt.Sprintf("%x", newConfigHash(c.storeableConfig.Config))
|
||||
c.storeableConfig.UpdatedAt = time.Now()
|
||||
c.flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -362,9 +435,7 @@ func (c *Config) DeleteRuleIDMatcher(ruleID string) error {
|
||||
}
|
||||
}
|
||||
|
||||
c.storeableConfig.Config = string(newRawFromConfig(c.alertmanagerConfig))
|
||||
c.storeableConfig.Hash = fmt.Sprintf("%x", newConfigHash(c.storeableConfig.Config))
|
||||
c.storeableConfig.UpdatedAt = time.Now()
|
||||
c.flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ func TestCreateRuleIDMatcher(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, receiver := range tc.receivers {
|
||||
err := cfg.CreateReceiver(receiver)
|
||||
err := cfg.CreateReceiver(&Receiver{Receiver: &receiver})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ func TestDeleteRuleIDMatcher(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, receiver := range tc.receivers {
|
||||
err := cfg.CreateReceiver(receiver)
|
||||
err := cfg.CreateReceiver(&Receiver{Receiver: &receiver})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -329,3 +329,58 @@ func TestSetGlobalConfigPreservesSMTPRequireTLS(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Round-trip: create → serialize → reload → GetReceiver still has the configs.
|
||||
func TestConfigPreservesGoogleChatConfigs(t *testing.T) {
|
||||
webhookURL, err := url.Parse("https://chat.googleapis.com/v1/spaces/test/messages")
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg, err := NewDefaultConfig(
|
||||
GlobalConfig{SMTPSmarthost: config.HostPort{Host: "localhost", Port: "25"}, SMTPFrom: "test@example.com"},
|
||||
RouteConfig{GroupInterval: time.Minute, GroupWait: time.Minute, RepeatInterval: time.Minute},
|
||||
"1",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
receiver := &Receiver{
|
||||
Receiver: &config.Receiver{Name: "googlechat-receiver"},
|
||||
GoogleChatConfigs: []*GoogleChatReceiverConfig{
|
||||
{
|
||||
WebhookURL: &config.SecretURL{URL: webhookURL},
|
||||
Title: "Alert",
|
||||
Text: "Body",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
require.NoError(t, cfg.CreateReceiver(receiver))
|
||||
|
||||
got, err := cfg.GetReceiver("googlechat-receiver")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, got.GoogleChatConfigs, 1)
|
||||
assert.Equal(t, "Alert", got.GoogleChatConfigs[0].Title)
|
||||
assert.Equal(t, "Body", got.GoogleChatConfigs[0].Text)
|
||||
|
||||
// HTTPConfig threaded from Global by applyNativeDefaults.
|
||||
require.NotNil(t, got.GoogleChatConfigs[0].HTTPConfig)
|
||||
assert.Same(t, cfg.alertmanagerConfig.Global.HTTPConfig, got.GoogleChatConfigs[0].HTTPConfig)
|
||||
|
||||
reloaded, err := NewConfigFromStoreableConfig(cfg.StoreableConfig())
|
||||
require.NoError(t, err)
|
||||
|
||||
reloadedReceiver, err := reloaded.GetReceiver("googlechat-receiver")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, reloadedReceiver.GoogleChatConfigs, 1)
|
||||
assert.Equal(t, "Alert", reloadedReceiver.GoogleChatConfigs[0].Title)
|
||||
assert.Equal(t, "Body", reloadedReceiver.GoogleChatConfigs[0].Text)
|
||||
assert.Equal(t, "https://chat.googleapis.com/v1/spaces/test/messages", reloadedReceiver.GoogleChatConfigs[0].WebhookURL.String())
|
||||
require.NotNil(t, reloadedReceiver.GoogleChatConfigs[0].HTTPConfig)
|
||||
|
||||
receiver.GoogleChatConfigs[0].Title = "Updated"
|
||||
require.NoError(t, cfg.UpdateReceiver(receiver))
|
||||
|
||||
updated, err := cfg.GetReceiver("googlechat-receiver")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, updated.GoogleChatConfigs, 1)
|
||||
assert.Equal(t, "Updated", updated.GoogleChatConfigs[0].Title)
|
||||
}
|
||||
|
||||
34
pkg/types/alertmanagertypes/googlechat.go
Normal file
34
pkg/types/alertmanagertypes/googlechat.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package alertmanagertypes
|
||||
|
||||
import (
|
||||
"github.com/prometheus/alertmanager/config"
|
||||
commoncfg "github.com/prometheus/common/config"
|
||||
)
|
||||
|
||||
type GoogleChatReceiverConfig struct {
|
||||
config.NotifierConfig `yaml:",inline" json:",inline"`
|
||||
|
||||
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
|
||||
|
||||
WebhookURL *config.SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"`
|
||||
Title string `yaml:"title,omitempty" json:"title,omitempty"`
|
||||
Text string `yaml:"text,omitempty" json:"text,omitempty"`
|
||||
}
|
||||
|
||||
var DefaultGoogleChatReceiverConfig = GoogleChatReceiverConfig{
|
||||
NotifierConfig: config.NotifierConfig{
|
||||
VSendResolved: false,
|
||||
},
|
||||
Title: `[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }}`,
|
||||
Text: `{{ range .Alerts -}}
|
||||
*Alert:* {{ .Labels.alertname }}{{ if .Labels.severity }} ({{ .Labels.severity }}){{ end }}{{ if .Annotations.summary }}
|
||||
*Summary:* {{ .Annotations.summary }}{{ end }}{{ if .Annotations.description }}
|
||||
*Description:* {{ .Annotations.description }}{{ end }}
|
||||
{{ end }}`,
|
||||
}
|
||||
|
||||
func (c *GoogleChatReceiverConfig) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
*c = DefaultGoogleChatReceiverConfig
|
||||
type plain GoogleChatReceiverConfig
|
||||
return unmarshal((*plain)(c))
|
||||
}
|
||||
@@ -22,7 +22,7 @@ func TestAddRuleIDToRoute(t *testing.T) {
|
||||
{
|
||||
name: "Simple",
|
||||
route: func() *config.Route {
|
||||
route, err := NewRouteFromReceiver(Receiver{Name: "test"})
|
||||
route, err := NewRouteFromReceiver(&Receiver{Receiver: &config.Receiver{Name: "test"}})
|
||||
require.NoError(t, err)
|
||||
|
||||
return route
|
||||
@@ -33,7 +33,7 @@ func TestAddRuleIDToRoute(t *testing.T) {
|
||||
{
|
||||
name: "AlreadyExists",
|
||||
route: func() *config.Route {
|
||||
route, err := NewRouteFromReceiver(Receiver{Name: "test"})
|
||||
route, err := NewRouteFromReceiver(&Receiver{Receiver: &config.Receiver{Name: "test"}})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = addRuleIDToRoute(route, "1")
|
||||
@@ -84,7 +84,7 @@ func TestRemoveRuleIDFromRoute(t *testing.T) {
|
||||
{
|
||||
name: "Simple",
|
||||
route: func() *config.Route {
|
||||
route, err := NewRouteFromReceiver(Receiver{Name: "test"})
|
||||
route, err := NewRouteFromReceiver(&Receiver{Receiver: &config.Receiver{Name: "test"}})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = addRuleIDToRoute(route, "1")
|
||||
@@ -98,7 +98,7 @@ func TestRemoveRuleIDFromRoute(t *testing.T) {
|
||||
{
|
||||
name: "DoesNotExist",
|
||||
route: func() *config.Route {
|
||||
route, err := NewRouteFromReceiver(Receiver{Name: "test"})
|
||||
route, err := NewRouteFromReceiver(&Receiver{Receiver: &config.Receiver{Name: "test"}})
|
||||
require.NoError(t, err)
|
||||
|
||||
return route
|
||||
@@ -109,7 +109,7 @@ func TestRemoveRuleIDFromRoute(t *testing.T) {
|
||||
{
|
||||
name: "DeleteMatcher",
|
||||
route: func() *config.Route {
|
||||
route, err := NewRouteFromReceiver(Receiver{Name: "test"})
|
||||
route, err := NewRouteFromReceiver(&Receiver{Receiver: &config.Receiver{Name: "test"}})
|
||||
require.NoError(t, err)
|
||||
|
||||
return route
|
||||
|
||||
@@ -17,4 +17,4 @@ type Templater interface {
|
||||
|
||||
// ReceiverIntegrationsFunc constructs the notify.Integration list for a
|
||||
// configured receiver.
|
||||
type ReceiverIntegrationsFunc = func(nc Receiver, tmpl *template.Template, logger *slog.Logger, templater Templater) ([]notify.Integration, error)
|
||||
type ReceiverIntegrationsFunc = func(nc *Receiver, tmpl *template.Template, logger *slog.Logger, templater Templater) ([]notify.Integration, error)
|
||||
|
||||
@@ -17,40 +17,73 @@ import (
|
||||
"github.com/prometheus/alertmanager/config"
|
||||
)
|
||||
|
||||
type (
|
||||
// Receiver is the type for the receiver configuration.
|
||||
Receiver = config.Receiver
|
||||
)
|
||||
|
||||
// Creates a new receiver from a string. The input is initialized with the default values from the upstream alertmanager.
|
||||
// The only default value which is missed is `send_resolved` (as it is a bool) which if not set in the input will always be set to `false`.
|
||||
func NewReceiver(input string) (Receiver, error) {
|
||||
receiver := Receiver{}
|
||||
err := json.Unmarshal([]byte(input), &receiver)
|
||||
if err != nil {
|
||||
return Receiver{}, err
|
||||
}
|
||||
|
||||
// We marshal and unmarshal the receiver to ensure that the receiver is
|
||||
// initialized with defaults from the upstream alertmanager.
|
||||
bytes, err := yaml.Marshal(receiver)
|
||||
if err != nil {
|
||||
return Receiver{}, err
|
||||
}
|
||||
|
||||
receiverWithDefaults := Receiver{}
|
||||
if err := yaml.Unmarshal(bytes, &receiverWithDefaults); err != nil {
|
||||
return Receiver{}, err
|
||||
}
|
||||
|
||||
if err := receiverWithDefaults.UnmarshalYAML(func(i interface{}) error { return nil }); err != nil {
|
||||
return Receiver{}, err
|
||||
}
|
||||
|
||||
return receiverWithDefaults, nil
|
||||
// Receiver embeds upstream config.Receiver to support custom receivers
|
||||
// To add another native notifier, mirror GoogleChatConfigs here
|
||||
// and extend customReceiverConfigs in config.go.
|
||||
type Receiver struct {
|
||||
*config.Receiver
|
||||
GoogleChatConfigs []*GoogleChatReceiverConfig `json:"googlechat_configs,omitempty" yaml:"googlechat_configs,omitempty"`
|
||||
}
|
||||
|
||||
func TestReceiver(ctx context.Context, receiver Receiver, receiverIntegrationsFunc ReceiverIntegrationsFunc, config *Config, tmpl *template.Template, logger *slog.Logger, templater Templater, lSet model.LabelSet, alert ...*Alert) error {
|
||||
// NewReceiver builds a Receiver from its JSON input, applying each notifier
|
||||
// config's per-config defaults via UnmarshalYAML.
|
||||
func NewReceiver(input string) (*Receiver, error) {
|
||||
receiver := &Receiver{Receiver: &config.Receiver{}}
|
||||
if err := json.Unmarshal([]byte(input), receiver); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
withDefaults, err := defaultedBaseReceiver(receiver.Receiver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
receiver.Receiver = withDefaults
|
||||
|
||||
// Extend this block when adding another native notifier type.
|
||||
for i, gc := range receiver.GoogleChatConfigs {
|
||||
defaulted, err := defaultedNotifierConfig(gc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
receiver.GoogleChatConfigs[i] = defaulted
|
||||
}
|
||||
|
||||
return receiver, nil
|
||||
}
|
||||
|
||||
func defaultedBaseReceiver(base *config.Receiver) (*config.Receiver, error) {
|
||||
bytes, err := yaml.Marshal(base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
withDefaults := &config.Receiver{}
|
||||
if err := yaml.Unmarshal(bytes, withDefaults); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := withDefaults.UnmarshalYAML(func(i interface{}) error { return nil }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return withDefaults, nil
|
||||
}
|
||||
|
||||
// defaultedNotifierConfig triggers T.UnmarshalYAML via a yaml round-trip,
|
||||
// installing T's DefaultXxxConfig over user values.
|
||||
func defaultedNotifierConfig[T any](cfg *T) (*T, error) {
|
||||
bytes, err := yaml.Marshal(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := new(T)
|
||||
if err := yaml.Unmarshal(bytes, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func TestReceiver(ctx context.Context, receiver *Receiver, receiverIntegrationsFunc ReceiverIntegrationsFunc, config *Config, tmpl *template.Template, logger *slog.Logger, templater Templater, lSet model.LabelSet, alert ...*Alert) error {
|
||||
ctx = notify.WithGroupKey(ctx, fmt.Sprintf("%s-%s-%d", receiver.Name, lSet.Fingerprint(), time.Now().Unix()))
|
||||
ctx = notify.WithGroupLabels(ctx, lSet)
|
||||
ctx = notify.WithReceiverName(ctx, receiver.Name)
|
||||
@@ -67,12 +100,12 @@ func TestReceiver(ctx context.Context, receiver Receiver, receiverIntegrationsFu
|
||||
return err
|
||||
}
|
||||
|
||||
receiver, err = testConfig.GetReceiver(receiver.Name)
|
||||
defaultedReceiver, err := testConfig.GetReceiver(receiver.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
integrations, err := receiverIntegrationsFunc(receiver, tmpl, logger, templater)
|
||||
integrations, err := receiverIntegrationsFunc(defaultedReceiver, tmpl, logger, templater)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -21,6 +21,12 @@ func TestNewReceiver(t *testing.T) {
|
||||
expected: `{"name":"telegram","telegram_configs":[{"send_resolved":false,"token":"1234567890","chat":12345,"message":"{{ template \"telegram.default.message\" . }}","parse_mode":"HTML"}]}`,
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
name: "GoogleChatConfig",
|
||||
input: `{"name":"googlechat","googlechat_configs":[{"webhook_url":"https://chat.googleapis.com/v1/spaces/test/messages","title":"Alert","text":"Body"}]}`,
|
||||
expected: `{"name":"googlechat","googlechat_configs":[{"send_resolved":false,"webhook_url":"https://chat.googleapis.com/v1/spaces/test/messages","title":"Alert","text":"Body"}]}`,
|
||||
pass: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
@@ -39,3 +45,27 @@ func TestNewReceiver(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Omitted fields fall back to DefaultGoogleChatReceiverConfig.
|
||||
func TestNewReceiverGoogleChatAppliesDefaults(t *testing.T) {
|
||||
receiver, err := NewReceiver(`{"name":"googlechat","googlechat_configs":[{"webhook_url":"https://chat.googleapis.com/v1/spaces/test/messages"}]}`)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, receiver.GoogleChatConfigs, 1)
|
||||
|
||||
got := receiver.GoogleChatConfigs[0]
|
||||
assert.Equal(t, DefaultGoogleChatReceiverConfig.Title, got.Title, "Title should fall back to the default template")
|
||||
assert.Equal(t, DefaultGoogleChatReceiverConfig.Text, got.Text, "Text should fall back to the default template")
|
||||
assert.Equal(t, DefaultGoogleChatReceiverConfig.VSendResolved, got.SendResolved(), "send_resolved should fall back to the default")
|
||||
}
|
||||
|
||||
// User-specified values override defaults.
|
||||
func TestNewReceiverGoogleChatPreservesUserOverrides(t *testing.T) {
|
||||
receiver, err := NewReceiver(`{"name":"googlechat","googlechat_configs":[{"webhook_url":"https://chat.googleapis.com/v1/spaces/test/messages","title":"X","text":"Y","send_resolved":true}]}`)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, receiver.GoogleChatConfigs, 1)
|
||||
|
||||
got := receiver.GoogleChatConfigs[0]
|
||||
assert.Equal(t, "X", got.Title)
|
||||
assert.Equal(t, "Y", got.Text)
|
||||
assert.True(t, got.SendResolved())
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func NewRouteFromRouteConfig(route *config.Route, cfg RouteConfig) (*config.Rout
|
||||
return route, nil
|
||||
}
|
||||
|
||||
func NewRouteFromReceiver(receiver Receiver) (*config.Route, error) {
|
||||
func NewRouteFromReceiver(receiver *Receiver) (*config.Route, error) {
|
||||
route := &config.Route{Receiver: receiver.Name, Continue: true, Matchers: config.Matchers{noRuleIDMatcher}}
|
||||
if err := route.UnmarshalYAML(func(i interface{}) error { return nil }); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -257,10 +257,7 @@ func (s SpaceAggregation) Percentile() float64 {
|
||||
}
|
||||
|
||||
// MetricTableHints is a struct that contains tables to use instead of the derived tables
|
||||
//
|
||||
// Convention :
|
||||
// - TimeSeriesTableName: the LOCAL table name (e.g. "time_series_v4_1day").
|
||||
// - SamplesTableName: the DISTRIBUTED table name (e.g. "distributed_samples_v4_agg_5m").
|
||||
// from the start and end time, for internal use only when we need to override the derived tables.
|
||||
type MetricTableHints struct {
|
||||
TimeSeriesTableName string
|
||||
SamplesTableName string
|
||||
|
||||
@@ -139,33 +139,6 @@ def test_get_service_details_with_account(
|
||||
assert data["id"] == SERVICE_ID
|
||||
assert data["cloudIntegrationService"] is None, "cloudIntegrationService should be null before any service config is set"
|
||||
|
||||
def test_get_account_service(
|
||||
signoz: types.SigNoz,
|
||||
create_user_admin: types.Operation, # pylint: disable=unused-argument
|
||||
get_token: Callable[[str, str], str],
|
||||
create_cloud_integration_account: Callable,
|
||||
) -> None:
|
||||
"""Get service for a specific account — all disabled by default."""
|
||||
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
|
||||
|
||||
account = create_cloud_integration_account(admin_token, CLOUD_PROVIDER)
|
||||
account_id = account["id"]
|
||||
|
||||
checkin = simulate_agent_checkin(signoz, admin_token, CLOUD_PROVIDER, account_id, str(uuid.uuid4()))
|
||||
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
|
||||
|
||||
response = requests.get(
|
||||
signoz.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}"),
|
||||
headers={"Authorization": f"Bearer {admin_token}"},
|
||||
timeout=10,
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK, f"Expected 200, got {response.status_code}"
|
||||
|
||||
data = response.json()["data"]
|
||||
assert data["id"] == SERVICE_ID, f"id should be '{SERVICE_ID}'"
|
||||
assert data["cloudIntegrationService"] is None, "cloudIntegrationService should be null before any config is set"
|
||||
|
||||
|
||||
def test_get_service_not_found(
|
||||
signoz: types.SigNoz,
|
||||
|
||||
Reference in New Issue
Block a user