diff --git a/.github/workflows/integrationci.yaml b/.github/workflows/integrationci.yaml index ca80a12ad31..30137c3b2ab 100644 --- a/.github/workflows/integrationci.yaml +++ b/.github/workflows/integrationci.yaml @@ -50,6 +50,7 @@ jobs: - logspipelines - passwordauthn - preference + - quickfilter - querierlogs - queriertraces - queriermetrics diff --git a/docs/api/openapi.yml b/docs/api/openapi.yml index 88ffeab9444..9c13b7e609a 100644 --- a/docs/api/openapi.yml +++ b/docs/api/openapi.yml @@ -109,6 +109,25 @@ components: webhook_url: $ref: '#/components/schemas/ConfigSecretURL' type: object + AlertmanagertypesIncidentIOReceiverConfig: + properties: + description: + type: string + http_config: + $ref: '#/components/schemas/ConfigHTTPClientConfig' + metadata: + additionalProperties: + type: string + type: object + send_resolved: + type: boolean + title: + type: string + token: + type: string + url: + type: string + type: object AlertmanagertypesJSMOpsReceiverConfig: properties: api_key: @@ -217,12 +236,12 @@ components: - jira_configs - required: - jsmops_configs + - required: + - incidentio_configs - required: - discord_configs - required: - email_configs - - required: - - incidentio_configs - required: - pagerduty_configs - required: @@ -266,7 +285,7 @@ components: type: array incidentio_configs: items: - $ref: '#/components/schemas/ConfigIncidentioConfig' + $ref: '#/components/schemas/AlertmanagertypesIncidentIOReceiverConfig' type: array jira_configs: items: @@ -397,7 +416,7 @@ components: type: array incidentio_configs: items: - $ref: '#/components/schemas/ConfigIncidentioConfig' + $ref: '#/components/schemas/AlertmanagertypesIncidentIOReceiverConfig' type: array jira_configs: items: @@ -4071,6 +4090,18 @@ components: nullable: true type: object type: object + GatewaytypesDeprecatedPostableIngestionKeyLimit: + properties: + config: + $ref: '#/components/schemas/GatewaytypesLimitConfig' + signal: + type: string + tags: + items: + type: string + nullable: true + type: array + type: object GatewaytypesGettableCreatedIngestionKey: properties: id: @@ -4214,6 +4245,8 @@ components: properties: config: $ref: '#/components/schemas/GatewaytypesLimitConfig' + keyId: + type: string signal: type: string tags: @@ -4221,6 +4254,8 @@ components: type: string nullable: true type: array + required: + - keyId type: object GatewaytypesUpdatableIngestionKeyLimit: properties: @@ -7838,6 +7873,48 @@ components: - custom - text type: string + QuickfiltertypesSource: + enum: + - traces + - logs + - api_monitoring + - exceptions + - meter + - ai_observability + type: string + QuickfiltertypesSourceFilters: + properties: + createdAt: + format: date-time + type: string + filters: + items: + $ref: '#/components/schemas/TelemetrytypesTelemetryFieldKey' + type: array + id: + type: string + orgId: + type: string + source: + $ref: '#/components/schemas/QuickfiltertypesSource' + updatedAt: + format: date-time + type: string + required: + - id + - orgId + - source + - filters + type: object + QuickfiltertypesUpdatableQuickFilters: + properties: + filters: + items: + $ref: '#/components/schemas/TelemetrytypesTelemetryFieldKey' + type: array + required: + - filters + type: object RenderErrorResponse: properties: error: @@ -9678,6 +9755,10 @@ paths: name: name schema: type: string + - in: query + name: existingQuery + schema: + type: string responses: "200": content: @@ -16046,9 +16127,9 @@ paths: description: Internal Server Error security: - api_key: - - EDITOR + - ingestion-key:list - tokenizer: - - EDITOR + - ingestion-key:list summary: Get ingestion keys for workspace tags: - gateway @@ -16096,9 +16177,9 @@ paths: description: Internal Server Error security: - api_key: - - EDITOR + - ingestion-key:create - tokenizer: - - EDITOR + - ingestion-key:create summary: Create ingestion key for workspace tags: - gateway @@ -16136,12 +16217,69 @@ paths: description: Internal Server Error security: - api_key: - - EDITOR + - ingestion-key:delete - tokenizer: - - EDITOR + - ingestion-key:delete summary: Delete ingestion key for workspace tags: - gateway + get: + deprecated: false + description: This endpoint returns an ingestion key for the workspace + operationId: GetIngestionKey + parameters: + - in: path + name: keyId + required: true + schema: + type: string + responses: + "200": + content: + application/json: + schema: + properties: + data: + $ref: '#/components/schemas/GatewaytypesIngestionKey' + status: + type: string + required: + - status + - data + type: object + description: OK + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Unauthorized + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Forbidden + "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: + - ingestion-key:read + - tokenizer: + - ingestion-key:read + summary: Get ingestion key for workspace + tags: + - gateway patch: deprecated: false description: This endpoint updates an ingestion key for the workspace @@ -16180,16 +16318,76 @@ paths: description: Internal Server Error security: - api_key: - - EDITOR + - ingestion-key:update - tokenizer: - - EDITOR + - ingestion-key:update summary: Update ingestion key for workspace tags: - gateway /api/v2/gateway/ingestion_keys/{keyId}/limits: - post: + get: deprecated: false - description: This endpoint creates an ingestion key limit + description: This endpoint returns the ingestion limits for an ingestion key + operationId: GetIngestionKeyLimits + parameters: + - in: path + name: keyId + required: true + schema: + type: string + responses: + "200": + content: + application/json: + schema: + properties: + data: + items: + $ref: '#/components/schemas/GatewaytypesLimit' + nullable: true + type: array + status: + type: string + required: + - status + - data + type: object + description: OK + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Unauthorized + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Forbidden + "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: + - ingestion-limit:list + - tokenizer: + - ingestion-limit:list + summary: Get limits for the ingestion key + tags: + - gateway + post: + deprecated: true + description: This endpoint creates an ingestion key limit. operationId: CreateIngestionKeyLimit parameters: - in: path @@ -16201,7 +16399,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/GatewaytypesPostableIngestionKeyLimit' + $ref: '#/components/schemas/GatewaytypesDeprecatedPostableIngestionKeyLimit' responses: "201": content: @@ -16237,15 +16435,17 @@ paths: description: Internal Server Error security: - api_key: - - EDITOR + - ingestion-limit:create + - ingestion-key:attach - tokenizer: - - EDITOR + - ingestion-limit:create + - ingestion-key:attach summary: Create limit for the ingestion key tags: - gateway /api/v2/gateway/ingestion_keys/limits/{limitId}: delete: - deprecated: false + deprecated: true description: This endpoint deletes an ingestion key limit operationId: DeleteIngestionKeyLimit parameters: @@ -16277,15 +16477,17 @@ paths: description: Internal Server Error security: - api_key: - - EDITOR + - ingestion-limit:delete + - ingestion-key:detach - tokenizer: - - EDITOR + - ingestion-limit:delete + - ingestion-key:detach summary: Delete limit for the ingestion key tags: - gateway patch: - deprecated: false - description: This endpoint updates an ingestion key limit + deprecated: true + description: This endpoint updates an ingestion key limit. operationId: UpdateIngestionKeyLimit parameters: - in: path @@ -16321,9 +16523,9 @@ paths: description: Internal Server Error security: - api_key: - - EDITOR + - ingestion-limit:update - tokenizer: - - EDITOR + - ingestion-limit:update summary: Update limit for the ingestion key tags: - gateway @@ -16381,12 +16583,215 @@ paths: description: Internal Server Error security: - api_key: - - EDITOR + - ingestion-key:list - tokenizer: - - EDITOR + - ingestion-key:list summary: Search ingestion keys for workspace tags: - gateway + /api/v2/gateway/ingestion_limits: + post: + deprecated: false + description: This endpoint creates an ingestion limit for the ingestion key + referenced by keyId + operationId: CreateIngestionLimit + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GatewaytypesPostableIngestionKeyLimit' + responses: + "201": + content: + application/json: + schema: + properties: + data: + $ref: '#/components/schemas/TypesIdentifiable' + status: + type: string + required: + - status + - data + type: object + description: Created + "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 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Internal Server Error + security: + - api_key: + - ingestion-limit:create + - ingestion-key:attach + - tokenizer: + - ingestion-limit:create + - ingestion-key:attach + summary: Create ingestion limit + tags: + - gateway + /api/v2/gateway/ingestion_limits/{limitId}: + delete: + deprecated: false + description: This endpoint deletes an ingestion limit + operationId: DeleteIngestionLimit + parameters: + - in: path + name: limitId + required: true + schema: + type: string + responses: + "204": + description: No Content + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Unauthorized + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Forbidden + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Internal Server Error + security: + - api_key: + - ingestion-limit:delete + - ingestion-key:detach + - tokenizer: + - ingestion-limit:delete + - ingestion-key:detach + summary: Delete ingestion limit + tags: + - gateway + get: + deprecated: false + description: This endpoint returns an ingestion limit + operationId: GetIngestionLimit + parameters: + - in: path + name: limitId + required: true + schema: + type: string + responses: + "200": + content: + application/json: + schema: + properties: + data: + $ref: '#/components/schemas/GatewaytypesLimit' + status: + type: string + required: + - status + - data + type: object + description: OK + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Unauthorized + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Forbidden + "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: + - ingestion-limit:read + - tokenizer: + - ingestion-limit:read + summary: Get ingestion limit + tags: + - gateway + patch: + deprecated: false + description: This endpoint updates an ingestion limit + operationId: UpdateIngestionLimit + parameters: + - in: path + name: limitId + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GatewaytypesUpdatableIngestionKeyLimit' + responses: + "204": + description: No Content + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Unauthorized + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Forbidden + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Internal Server Error + security: + - api_key: + - ingestion-limit:update + - tokenizer: + - ingestion-limit:update + summary: Update ingestion limit + tags: + - gateway /api/v2/healthz: get: operationId: Healthz @@ -18841,6 +19246,170 @@ paths: summary: Get query range result (v2) tags: - dashboard + /api/v2/quick_filters: + get: + deprecated: false + description: Returns the org's quick filters for every source, each filter as + a telemetry field key. + operationId: ListQuickFilters + responses: + "200": + content: + application/json: + schema: + properties: + data: + items: + $ref: '#/components/schemas/QuickfiltertypesSourceFilters' + type: array + 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 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Internal Server Error + security: + - api_key: + - quick-filter:list + - tokenizer: + - quick-filter:list + summary: List quick filters + tags: + - quick_filter + /api/v2/quick_filters/{source}: + get: + deprecated: false + description: Returns the org's quick filters for one source, each filter as + a telemetry field key. + operationId: GetQuickFilters + parameters: + - in: path + name: source + required: true + schema: + type: string + responses: + "200": + content: + application/json: + schema: + properties: + data: + $ref: '#/components/schemas/QuickfiltertypesSourceFilters' + 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 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Internal Server Error + security: + - api_key: + - quick-filter:read + - tokenizer: + - quick-filter:read + summary: Get a source's quick filters + tags: + - quick_filter + put: + deprecated: false + description: Replaces the org's quick filters for the source named in the path. + operationId: UpdateQuickFilters + parameters: + - in: path + name: source + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/QuickfiltertypesUpdatableQuickFilters' + responses: + "204": + description: No Content + "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 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/RenderErrorResponse' + description: Internal Server Error + security: + - api_key: + - quick-filter:update + - tokenizer: + - quick-filter:update + summary: Update quick filters + tags: + - quick_filter /api/v2/readyz: get: operationId: Readyz diff --git a/ee/gateway/httpgateway/provider.go b/ee/gateway/httpgateway/provider.go index 944db4046e3..5b72598d197 100644 --- a/ee/gateway/httpgateway/provider.go +++ b/ee/gateway/httpgateway/provider.go @@ -108,6 +108,20 @@ func (provider *Provider) SearchIngestionKeysByName(ctx context.Context, orgID v }, nil } +func (provider *Provider) GetIngestionKey(ctx context.Context, orgID valuer.UUID, keyID string) (*gatewaytypes.IngestionKey, error) { + responseBody, err := provider.do(ctx, orgID, http.MethodGet, "/v1/workspaces/me/keys/"+keyID, nil, nil) + if err != nil { + return nil, err + } + + var ingestionKey gatewaytypes.IngestionKey + if err := json.Unmarshal([]byte(gjson.GetBytes(responseBody, "data").String()), &ingestionKey); err != nil { + return nil, err + } + + return &ingestionKey, nil +} + func (provider *Provider) CreateIngestionKey(ctx context.Context, orgID valuer.UUID, name string, tags []string, expiresAt time.Time) (*gatewaytypes.GettableCreatedIngestionKey, error) { requestBody := gatewaytypes.PostableIngestionKey{ Name: name, @@ -161,7 +175,7 @@ func (provider *Provider) DeleteIngestionKey(ctx context.Context, orgID valuer.U } func (provider *Provider) CreateIngestionKeyLimit(ctx context.Context, orgID valuer.UUID, keyID string, signal string, limitConfig gatewaytypes.LimitConfig, tags []string) (*gatewaytypes.GettableCreatedIngestionKeyLimit, error) { - requestBody := gatewaytypes.PostableIngestionKeyLimit{ + requestBody := gatewaytypes.DeprecatedPostableIngestionKeyLimit{ Signal: signal, Config: limitConfig, Tags: tags, @@ -184,6 +198,34 @@ func (provider *Provider) CreateIngestionKeyLimit(ctx context.Context, orgID val return &createdIngestionKeyLimitResponse, nil } +func (provider *Provider) GetIngestionKeyLimit(ctx context.Context, orgID valuer.UUID, limitID string) (*gatewaytypes.Limit, error) { + responseBody, err := provider.do(ctx, orgID, http.MethodGet, "/v1/workspaces/me/limits/"+limitID, nil, nil) + if err != nil { + return nil, err + } + + var limit gatewaytypes.Limit + if err := json.Unmarshal([]byte(gjson.GetBytes(responseBody, "data").String()), &limit); err != nil { + return nil, err + } + + return &limit, nil +} + +func (provider *Provider) GetIngestionKeyLimits(ctx context.Context, orgID valuer.UUID, keyID string) ([]gatewaytypes.Limit, error) { + responseBody, err := provider.do(ctx, orgID, http.MethodGet, "/v1/workspaces/me/keys/"+keyID+"/limits", nil, nil) + if err != nil { + return nil, err + } + + var limits []gatewaytypes.Limit + if err := json.Unmarshal([]byte(gjson.GetBytes(responseBody, "data").String()), &limits); err != nil { + return nil, err + } + + return limits, nil +} + func (provider *Provider) UpdateIngestionKeyLimit(ctx context.Context, orgID valuer.UUID, limitID string, limitConfig gatewaytypes.LimitConfig, tags []string) error { requestBody := gatewaytypes.UpdatableIngestionKeyLimit{ Config: limitConfig, diff --git a/frontend/public/locales/en-GB/channels.json b/frontend/public/locales/en-GB/channels.json index 9043f73bb5a..51595bdd10e 100644 --- a/frontend/public/locales/en-GB/channels.json +++ b/frontend/public/locales/en-GB/channels.json @@ -75,6 +75,23 @@ "field_jsmops_tags": "Tags", "placeholder_jsmops_tags": "Type a tag and press Enter", "help_jsmops_tags": "Tags added to every alert.", + "incidentio_tip": "Create an HTTP alert source in incident.io (On-call \u2192 Alert routing \u2192 Sources) and paste its URL and token below.", + "incidentio_tip_link": "Learn how", + "field_incidentio_url": "Alert source URL", + "help_incidentio_url": "The alert events URL from the source's setup page, e.g. https://api.incident.io/v2/alert_events/http/.", + "field_incidentio_token": "Token", + "help_incidentio_token": "The alert source's secret token, from the same setup page.", + "field_incidentio_title": "Title", + "help_incidentio_title": "Template for the alert title. Kept stable while the alert fires \u2014 incident.io ignores content updates on repeat events.", + "field_incidentio_description": "Description", + "help_incidentio_description": "Template for the alert description. Markdown, rendered natively by incident.io.", + "incidentio_required_fields": "Alert source URL and token are required", + "incidentio_url_invalid": "URL must be an incident.io alert events URL (https://api.incident.io/v2/alert_events/http/)", + "field_incidentio_metadata": "Additional metadata", + "help_incidentio_metadata": "Key-value pairs added to every alert's metadata, on top of the alert's labels (these win on a key clash). Values may use templates, e.g. {{ .CommonLabels.severity }}.", + "placeholder_incidentio_metadata_key": "Key", + "placeholder_incidentio_metadata_value": "Value", + "button_incidentio_add_metadata": "Add metadata", "field_slack_recipient": "Recipient", "field_slack_title": "Title", diff --git a/frontend/public/locales/en/channels.json b/frontend/public/locales/en/channels.json index 915d8770904..ec3b3ce5e3e 100644 --- a/frontend/public/locales/en/channels.json +++ b/frontend/public/locales/en/channels.json @@ -75,6 +75,23 @@ "field_jsmops_tags": "Tags", "placeholder_jsmops_tags": "Type a tag and press Enter", "help_jsmops_tags": "Tags added to every alert.", + "incidentio_tip": "Create an HTTP alert source in incident.io (On-call \u2192 Alert routing \u2192 Sources) and paste its URL and token below.", + "incidentio_tip_link": "Learn how", + "field_incidentio_url": "Alert source URL", + "help_incidentio_url": "The alert events URL from the source's setup page, e.g. https://api.incident.io/v2/alert_events/http/.", + "field_incidentio_token": "Token", + "help_incidentio_token": "The alert source's secret token, from the same setup page.", + "field_incidentio_title": "Title", + "help_incidentio_title": "Template for the alert title. Kept stable while the alert fires \u2014 incident.io ignores content updates on repeat events.", + "field_incidentio_description": "Description", + "help_incidentio_description": "Template for the alert description. Markdown, rendered natively by incident.io.", + "incidentio_required_fields": "Alert source URL and token are required", + "incidentio_url_invalid": "URL must be an incident.io alert events URL (https://api.incident.io/v2/alert_events/http/)", + "field_incidentio_metadata": "Additional metadata", + "help_incidentio_metadata": "Key-value pairs added to every alert's metadata, on top of the alert's labels (these win on a key clash). Values may use templates, e.g. {{ .CommonLabels.severity }}.", + "placeholder_incidentio_metadata_key": "Key", + "placeholder_incidentio_metadata_value": "Value", + "button_incidentio_add_metadata": "Add metadata", "field_slack_recipient": "Recipient", "field_slack_title": "Title", "field_slack_description": "Description", diff --git a/frontend/src/api/generated/services/gateway/index.ts b/frontend/src/api/generated/services/gateway/index.ts index fdcb3c472e7..eafa0f640c8 100644 --- a/frontend/src/api/generated/services/gateway/index.ts +++ b/frontend/src/api/generated/services/gateway/index.ts @@ -21,18 +21,28 @@ import type { CreateIngestionKey201, CreateIngestionKeyLimit201, CreateIngestionKeyLimitPathParameters, + CreateIngestionLimit201, DeleteIngestionKeyLimitPathParameters, DeleteIngestionKeyPathParameters, + DeleteIngestionLimitPathParameters, + GatewaytypesDeprecatedPostableIngestionKeyLimitDTO, GatewaytypesPostableIngestionKeyDTO, GatewaytypesPostableIngestionKeyLimitDTO, GatewaytypesUpdatableIngestionKeyLimitDTO, + GetIngestionKey200, + GetIngestionKeyLimits200, + GetIngestionKeyLimitsPathParameters, + GetIngestionKeyPathParameters, GetIngestionKeys200, GetIngestionKeysParams, + GetIngestionLimit200, + GetIngestionLimitPathParameters, RenderErrorResponseDTO, SearchIngestionKeys200, SearchIngestionKeysParams, UpdateIngestionKeyLimitPathParameters, UpdateIngestionKeyPathParameters, + UpdateIngestionLimitPathParameters, } from '../sigNoz.schemas'; import { GeneratedAPIInstance } from '../../../generatedAPIInstance'; @@ -300,6 +310,108 @@ export const useDeleteIngestionKey = < > => { return useMutation(getDeleteIngestionKeyMutationOptions(options)); }; +/** + * This endpoint returns an ingestion key for the workspace + * @summary Get ingestion key for workspace + */ +export const getIngestionKey = ( + { keyId }: GetIngestionKeyPathParameters, + signal?: AbortSignal, +) => { + return GeneratedAPIInstance({ + url: `/api/v2/gateway/ingestion_keys/${keyId}`, + method: 'GET', + signal, + }); +}; + +export const getGetIngestionKeyQueryKey = ({ + keyId, +}: GetIngestionKeyPathParameters) => { + return [`/api/v2/gateway/ingestion_keys/${keyId}`] as const; +}; + +export const getGetIngestionKeyQueryOptions = < + TData = Awaited>, + TError = ErrorType, +>( + { keyId }: GetIngestionKeyPathParameters, + options?: { + query?: UseQueryOptions< + Awaited>, + TError, + TData + >; + }, +) => { + const { query: queryOptions } = options ?? {}; + + const queryKey = + queryOptions?.queryKey ?? getGetIngestionKeyQueryKey({ keyId }); + + const queryFn: QueryFunction>> = ({ + signal, + }) => getIngestionKey({ keyId }, signal); + + return { + queryKey, + queryFn, + enabled: !!keyId, + ...queryOptions, + } as UseQueryOptions< + Awaited>, + TError, + TData + > & { queryKey: QueryKey }; +}; + +export type GetIngestionKeyQueryResult = NonNullable< + Awaited> +>; +export type GetIngestionKeyQueryError = ErrorType; + +/** + * @summary Get ingestion key for workspace + */ + +export function useGetIngestionKey< + TData = Awaited>, + TError = ErrorType, +>( + { keyId }: GetIngestionKeyPathParameters, + options?: { + query?: UseQueryOptions< + Awaited>, + TError, + TData + >; + }, +): UseQueryResult & { queryKey: QueryKey } { + const queryOptions = getGetIngestionKeyQueryOptions({ keyId }, options); + + const query = useQuery(queryOptions) as UseQueryResult & { + queryKey: QueryKey; + }; + + return { ...query, queryKey: queryOptions.queryKey }; +} + +/** + * @summary Get ingestion key for workspace + */ +export const invalidateGetIngestionKey = async ( + queryClient: QueryClient, + { keyId }: GetIngestionKeyPathParameters, + options?: InvalidateOptions, +): Promise => { + await queryClient.invalidateQueries( + { queryKey: getGetIngestionKeyQueryKey({ keyId }) }, + options, + ); + + return queryClient; +}; + /** * This endpoint updates an ingestion key for the workspace * @summary Update ingestion key for workspace @@ -400,19 +512,122 @@ export const useUpdateIngestionKey = < return useMutation(getUpdateIngestionKeyMutationOptions(options)); }; /** - * This endpoint creates an ingestion key limit + * This endpoint returns the ingestion limits for an ingestion key + * @summary Get limits for the ingestion key + */ +export const getIngestionKeyLimits = ( + { keyId }: GetIngestionKeyLimitsPathParameters, + signal?: AbortSignal, +) => { + return GeneratedAPIInstance({ + url: `/api/v2/gateway/ingestion_keys/${keyId}/limits`, + method: 'GET', + signal, + }); +}; + +export const getGetIngestionKeyLimitsQueryKey = ({ + keyId, +}: GetIngestionKeyLimitsPathParameters) => { + return [`/api/v2/gateway/ingestion_keys/${keyId}/limits`] as const; +}; + +export const getGetIngestionKeyLimitsQueryOptions = < + TData = Awaited>, + TError = ErrorType, +>( + { keyId }: GetIngestionKeyLimitsPathParameters, + options?: { + query?: UseQueryOptions< + Awaited>, + TError, + TData + >; + }, +) => { + const { query: queryOptions } = options ?? {}; + + const queryKey = + queryOptions?.queryKey ?? getGetIngestionKeyLimitsQueryKey({ keyId }); + + const queryFn: QueryFunction< + Awaited> + > = ({ signal }) => getIngestionKeyLimits({ keyId }, signal); + + return { + queryKey, + queryFn, + enabled: !!keyId, + ...queryOptions, + } as UseQueryOptions< + Awaited>, + TError, + TData + > & { queryKey: QueryKey }; +}; + +export type GetIngestionKeyLimitsQueryResult = NonNullable< + Awaited> +>; +export type GetIngestionKeyLimitsQueryError = ErrorType; + +/** + * @summary Get limits for the ingestion key + */ + +export function useGetIngestionKeyLimits< + TData = Awaited>, + TError = ErrorType, +>( + { keyId }: GetIngestionKeyLimitsPathParameters, + options?: { + query?: UseQueryOptions< + Awaited>, + TError, + TData + >; + }, +): UseQueryResult & { queryKey: QueryKey } { + const queryOptions = getGetIngestionKeyLimitsQueryOptions({ keyId }, options); + + const query = useQuery(queryOptions) as UseQueryResult & { + queryKey: QueryKey; + }; + + return { ...query, queryKey: queryOptions.queryKey }; +} + +/** + * @summary Get limits for the ingestion key + */ +export const invalidateGetIngestionKeyLimits = async ( + queryClient: QueryClient, + { keyId }: GetIngestionKeyLimitsPathParameters, + options?: InvalidateOptions, +): Promise => { + await queryClient.invalidateQueries( + { queryKey: getGetIngestionKeyLimitsQueryKey({ keyId }) }, + options, + ); + + return queryClient; +}; + +/** + * This endpoint creates an ingestion key limit. + * @deprecated * @summary Create limit for the ingestion key */ export const createIngestionKeyLimit = ( { keyId }: CreateIngestionKeyLimitPathParameters, - gatewaytypesPostableIngestionKeyLimitDTO?: BodyType, + gatewaytypesDeprecatedPostableIngestionKeyLimitDTO?: BodyType, signal?: AbortSignal, ) => { return GeneratedAPIInstance({ url: `/api/v2/gateway/ingestion_keys/${keyId}/limits`, method: 'POST', headers: { 'Content-Type': 'application/json' }, - data: gatewaytypesPostableIngestionKeyLimitDTO, + data: gatewaytypesDeprecatedPostableIngestionKeyLimitDTO, signal, }); }; @@ -426,7 +641,7 @@ export const getCreateIngestionKeyLimitMutationOptions = < TError, { pathParams: CreateIngestionKeyLimitPathParameters; - data?: BodyType; + data?: BodyType; }, TContext >; @@ -435,7 +650,7 @@ export const getCreateIngestionKeyLimitMutationOptions = < TError, { pathParams: CreateIngestionKeyLimitPathParameters; - data?: BodyType; + data?: BodyType; }, TContext > => { @@ -452,7 +667,7 @@ export const getCreateIngestionKeyLimitMutationOptions = < Awaited>, { pathParams: CreateIngestionKeyLimitPathParameters; - data?: BodyType; + data?: BodyType; } > = (props) => { const { pathParams, data } = props ?? {}; @@ -467,12 +682,13 @@ export type CreateIngestionKeyLimitMutationResult = NonNullable< Awaited> >; export type CreateIngestionKeyLimitMutationBody = - | BodyType + | BodyType | undefined; export type CreateIngestionKeyLimitMutationError = ErrorType; /** + * @deprecated * @summary Create limit for the ingestion key */ export const useCreateIngestionKeyLimit = < @@ -484,7 +700,7 @@ export const useCreateIngestionKeyLimit = < TError, { pathParams: CreateIngestionKeyLimitPathParameters; - data?: BodyType; + data?: BodyType; }, TContext >; @@ -493,7 +709,7 @@ export const useCreateIngestionKeyLimit = < TError, { pathParams: CreateIngestionKeyLimitPathParameters; - data?: BodyType; + data?: BodyType; }, TContext > => { @@ -501,6 +717,7 @@ export const useCreateIngestionKeyLimit = < }; /** * This endpoint deletes an ingestion key limit + * @deprecated * @summary Delete limit for the ingestion key */ export const deleteIngestionKeyLimit = ( @@ -559,6 +776,7 @@ export type DeleteIngestionKeyLimitMutationError = ErrorType; /** + * @deprecated * @summary Delete limit for the ingestion key */ export const useDeleteIngestionKeyLimit = < @@ -580,7 +798,8 @@ export const useDeleteIngestionKeyLimit = < return useMutation(getDeleteIngestionKeyLimitMutationOptions(options)); }; /** - * This endpoint updates an ingestion key limit + * This endpoint updates an ingestion key limit. + * @deprecated * @summary Update limit for the ingestion key */ export const updateIngestionKeyLimit = ( @@ -653,6 +872,7 @@ export type UpdateIngestionKeyLimitMutationError = ErrorType; /** + * @deprecated * @summary Update limit for the ingestion key */ export const useUpdateIngestionKeyLimit = < @@ -779,3 +999,370 @@ export const invalidateSearchIngestionKeys = async ( return queryClient; }; + +/** + * This endpoint creates an ingestion limit for the ingestion key referenced by keyId + * @summary Create ingestion limit + */ +export const createIngestionLimit = ( + gatewaytypesPostableIngestionKeyLimitDTO?: BodyType, + signal?: AbortSignal, +) => { + return GeneratedAPIInstance({ + url: `/api/v2/gateway/ingestion_limits`, + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + data: gatewaytypesPostableIngestionKeyLimitDTO, + signal, + }); +}; + +export const getCreateIngestionLimitMutationOptions = < + TError = ErrorType, + TContext = unknown, +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { data?: BodyType }, + TContext + >; +}): UseMutationOptions< + Awaited>, + TError, + { data?: BodyType }, + TContext +> => { + const mutationKey = ['createIngestionLimit']; + const { mutation: mutationOptions } = options + ? options.mutation && + 'mutationKey' in options.mutation && + options.mutation.mutationKey + ? options + : { ...options, mutation: { ...options.mutation, mutationKey } } + : { mutation: { mutationKey } }; + + const mutationFn: MutationFunction< + Awaited>, + { data?: BodyType } + > = (props) => { + const { data } = props ?? {}; + + return createIngestionLimit(data); + }; + + return { mutationFn, ...mutationOptions }; +}; + +export type CreateIngestionLimitMutationResult = NonNullable< + Awaited> +>; +export type CreateIngestionLimitMutationBody = + | BodyType + | undefined; +export type CreateIngestionLimitMutationError = + ErrorType; + +/** + * @summary Create ingestion limit + */ +export const useCreateIngestionLimit = < + TError = ErrorType, + TContext = unknown, +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { data?: BodyType }, + TContext + >; +}): UseMutationResult< + Awaited>, + TError, + { data?: BodyType }, + TContext +> => { + return useMutation(getCreateIngestionLimitMutationOptions(options)); +}; +/** + * This endpoint deletes an ingestion limit + * @summary Delete ingestion limit + */ +export const deleteIngestionLimit = ( + { limitId }: DeleteIngestionLimitPathParameters, + signal?: AbortSignal, +) => { + return GeneratedAPIInstance({ + url: `/api/v2/gateway/ingestion_limits/${limitId}`, + method: 'DELETE', + signal, + }); +}; + +export const getDeleteIngestionLimitMutationOptions = < + TError = ErrorType, + TContext = unknown, +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { pathParams: DeleteIngestionLimitPathParameters }, + TContext + >; +}): UseMutationOptions< + Awaited>, + TError, + { pathParams: DeleteIngestionLimitPathParameters }, + TContext +> => { + const mutationKey = ['deleteIngestionLimit']; + const { mutation: mutationOptions } = options + ? options.mutation && + 'mutationKey' in options.mutation && + options.mutation.mutationKey + ? options + : { ...options, mutation: { ...options.mutation, mutationKey } } + : { mutation: { mutationKey } }; + + const mutationFn: MutationFunction< + Awaited>, + { pathParams: DeleteIngestionLimitPathParameters } + > = (props) => { + const { pathParams } = props ?? {}; + + return deleteIngestionLimit(pathParams); + }; + + return { mutationFn, ...mutationOptions }; +}; + +export type DeleteIngestionLimitMutationResult = NonNullable< + Awaited> +>; + +export type DeleteIngestionLimitMutationError = + ErrorType; + +/** + * @summary Delete ingestion limit + */ +export const useDeleteIngestionLimit = < + TError = ErrorType, + TContext = unknown, +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { pathParams: DeleteIngestionLimitPathParameters }, + TContext + >; +}): UseMutationResult< + Awaited>, + TError, + { pathParams: DeleteIngestionLimitPathParameters }, + TContext +> => { + return useMutation(getDeleteIngestionLimitMutationOptions(options)); +}; +/** + * This endpoint returns an ingestion limit + * @summary Get ingestion limit + */ +export const getIngestionLimit = ( + { limitId }: GetIngestionLimitPathParameters, + signal?: AbortSignal, +) => { + return GeneratedAPIInstance({ + url: `/api/v2/gateway/ingestion_limits/${limitId}`, + method: 'GET', + signal, + }); +}; + +export const getGetIngestionLimitQueryKey = ({ + limitId, +}: GetIngestionLimitPathParameters) => { + return [`/api/v2/gateway/ingestion_limits/${limitId}`] as const; +}; + +export const getGetIngestionLimitQueryOptions = < + TData = Awaited>, + TError = ErrorType, +>( + { limitId }: GetIngestionLimitPathParameters, + options?: { + query?: UseQueryOptions< + Awaited>, + TError, + TData + >; + }, +) => { + const { query: queryOptions } = options ?? {}; + + const queryKey = + queryOptions?.queryKey ?? getGetIngestionLimitQueryKey({ limitId }); + + const queryFn: QueryFunction< + Awaited> + > = ({ signal }) => getIngestionLimit({ limitId }, signal); + + return { + queryKey, + queryFn, + enabled: !!limitId, + ...queryOptions, + } as UseQueryOptions< + Awaited>, + TError, + TData + > & { queryKey: QueryKey }; +}; + +export type GetIngestionLimitQueryResult = NonNullable< + Awaited> +>; +export type GetIngestionLimitQueryError = ErrorType; + +/** + * @summary Get ingestion limit + */ + +export function useGetIngestionLimit< + TData = Awaited>, + TError = ErrorType, +>( + { limitId }: GetIngestionLimitPathParameters, + options?: { + query?: UseQueryOptions< + Awaited>, + TError, + TData + >; + }, +): UseQueryResult & { queryKey: QueryKey } { + const queryOptions = getGetIngestionLimitQueryOptions({ limitId }, options); + + const query = useQuery(queryOptions) as UseQueryResult & { + queryKey: QueryKey; + }; + + return { ...query, queryKey: queryOptions.queryKey }; +} + +/** + * @summary Get ingestion limit + */ +export const invalidateGetIngestionLimit = async ( + queryClient: QueryClient, + { limitId }: GetIngestionLimitPathParameters, + options?: InvalidateOptions, +): Promise => { + await queryClient.invalidateQueries( + { queryKey: getGetIngestionLimitQueryKey({ limitId }) }, + options, + ); + + return queryClient; +}; + +/** + * This endpoint updates an ingestion limit + * @summary Update ingestion limit + */ +export const updateIngestionLimit = ( + { limitId }: UpdateIngestionLimitPathParameters, + gatewaytypesUpdatableIngestionKeyLimitDTO?: BodyType, + signal?: AbortSignal, +) => { + return GeneratedAPIInstance({ + url: `/api/v2/gateway/ingestion_limits/${limitId}`, + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + data: gatewaytypesUpdatableIngestionKeyLimitDTO, + signal, + }); +}; + +export const getUpdateIngestionLimitMutationOptions = < + TError = ErrorType, + TContext = unknown, +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { + pathParams: UpdateIngestionLimitPathParameters; + data?: BodyType; + }, + TContext + >; +}): UseMutationOptions< + Awaited>, + TError, + { + pathParams: UpdateIngestionLimitPathParameters; + data?: BodyType; + }, + TContext +> => { + const mutationKey = ['updateIngestionLimit']; + const { mutation: mutationOptions } = options + ? options.mutation && + 'mutationKey' in options.mutation && + options.mutation.mutationKey + ? options + : { ...options, mutation: { ...options.mutation, mutationKey } } + : { mutation: { mutationKey } }; + + const mutationFn: MutationFunction< + Awaited>, + { + pathParams: UpdateIngestionLimitPathParameters; + data?: BodyType; + } + > = (props) => { + const { pathParams, data } = props ?? {}; + + return updateIngestionLimit(pathParams, data); + }; + + return { mutationFn, ...mutationOptions }; +}; + +export type UpdateIngestionLimitMutationResult = NonNullable< + Awaited> +>; +export type UpdateIngestionLimitMutationBody = + | BodyType + | undefined; +export type UpdateIngestionLimitMutationError = + ErrorType; + +/** + * @summary Update ingestion limit + */ +export const useUpdateIngestionLimit = < + TError = ErrorType, + TContext = unknown, +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { + pathParams: UpdateIngestionLimitPathParameters; + data?: BodyType; + }, + TContext + >; +}): UseMutationResult< + Awaited>, + TError, + { + pathParams: UpdateIngestionLimitPathParameters; + data?: BodyType; + }, + TContext +> => { + return useMutation(getUpdateIngestionLimitMutationOptions(options)); +}; diff --git a/frontend/src/api/generated/services/quick-filter/index.ts b/frontend/src/api/generated/services/quick-filter/index.ts new file mode 100644 index 00000000000..5d43d975b25 --- /dev/null +++ b/frontend/src/api/generated/services/quick-filter/index.ts @@ -0,0 +1,316 @@ +/** + * ! Do not edit manually + * * The file has been auto-generated using Orval for SigNoz + * * regenerate with 'pnpm generate:api' + * SigNoz + */ +import { useMutation, useQuery } from 'react-query'; +import type { + InvalidateOptions, + MutationFunction, + QueryClient, + QueryFunction, + QueryKey, + UseMutationOptions, + UseMutationResult, + UseQueryOptions, + UseQueryResult, +} from 'react-query'; + +import type { + GetQuickFilters200, + GetQuickFiltersPathParameters, + ListQuickFilters200, + QuickfiltertypesUpdatableQuickFiltersDTO, + RenderErrorResponseDTO, + UpdateQuickFiltersPathParameters, +} from '../sigNoz.schemas'; + +import { GeneratedAPIInstance } from '../../../generatedAPIInstance'; +import type { ErrorType, BodyType } from '../../../generatedAPIInstance'; + +/** + * Returns the org's quick filters for every source, each filter as a telemetry field key. + * @summary List quick filters + */ +export const listQuickFilters = (signal?: AbortSignal) => { + return GeneratedAPIInstance({ + url: `/api/v2/quick_filters`, + method: 'GET', + signal, + }); +}; + +export const getListQuickFiltersQueryKey = () => { + return [`/api/v2/quick_filters`] as const; +}; + +export const getListQuickFiltersQueryOptions = < + TData = Awaited>, + TError = ErrorType, +>(options?: { + query?: UseQueryOptions< + Awaited>, + TError, + TData + >; +}) => { + const { query: queryOptions } = options ?? {}; + + const queryKey = queryOptions?.queryKey ?? getListQuickFiltersQueryKey(); + + const queryFn: QueryFunction>> = ({ + signal, + }) => listQuickFilters(signal); + + return { queryKey, queryFn, ...queryOptions } as UseQueryOptions< + Awaited>, + TError, + TData + > & { queryKey: QueryKey }; +}; + +export type ListQuickFiltersQueryResult = NonNullable< + Awaited> +>; +export type ListQuickFiltersQueryError = ErrorType; + +/** + * @summary List quick filters + */ + +export function useListQuickFilters< + TData = Awaited>, + TError = ErrorType, +>(options?: { + query?: UseQueryOptions< + Awaited>, + TError, + TData + >; +}): UseQueryResult & { queryKey: QueryKey } { + const queryOptions = getListQuickFiltersQueryOptions(options); + + const query = useQuery(queryOptions) as UseQueryResult & { + queryKey: QueryKey; + }; + + return { ...query, queryKey: queryOptions.queryKey }; +} + +/** + * @summary List quick filters + */ +export const invalidateListQuickFilters = async ( + queryClient: QueryClient, + options?: InvalidateOptions, +): Promise => { + await queryClient.invalidateQueries( + { queryKey: getListQuickFiltersQueryKey() }, + options, + ); + + return queryClient; +}; + +/** + * Returns the org's quick filters for one source, each filter as a telemetry field key. + * @summary Get a source's quick filters + */ +export const getQuickFilters = ( + { source }: GetQuickFiltersPathParameters, + signal?: AbortSignal, +) => { + return GeneratedAPIInstance({ + url: `/api/v2/quick_filters/${source}`, + method: 'GET', + signal, + }); +}; + +export const getGetQuickFiltersQueryKey = ({ + source, +}: GetQuickFiltersPathParameters) => { + return [`/api/v2/quick_filters/${source}`] as const; +}; + +export const getGetQuickFiltersQueryOptions = < + TData = Awaited>, + TError = ErrorType, +>( + { source }: GetQuickFiltersPathParameters, + options?: { + query?: UseQueryOptions< + Awaited>, + TError, + TData + >; + }, +) => { + const { query: queryOptions } = options ?? {}; + + const queryKey = + queryOptions?.queryKey ?? getGetQuickFiltersQueryKey({ source }); + + const queryFn: QueryFunction>> = ({ + signal, + }) => getQuickFilters({ source }, signal); + + return { + queryKey, + queryFn, + enabled: !!source, + ...queryOptions, + } as UseQueryOptions< + Awaited>, + TError, + TData + > & { queryKey: QueryKey }; +}; + +export type GetQuickFiltersQueryResult = NonNullable< + Awaited> +>; +export type GetQuickFiltersQueryError = ErrorType; + +/** + * @summary Get a source's quick filters + */ + +export function useGetQuickFilters< + TData = Awaited>, + TError = ErrorType, +>( + { source }: GetQuickFiltersPathParameters, + options?: { + query?: UseQueryOptions< + Awaited>, + TError, + TData + >; + }, +): UseQueryResult & { queryKey: QueryKey } { + const queryOptions = getGetQuickFiltersQueryOptions({ source }, options); + + const query = useQuery(queryOptions) as UseQueryResult & { + queryKey: QueryKey; + }; + + return { ...query, queryKey: queryOptions.queryKey }; +} + +/** + * @summary Get a source's quick filters + */ +export const invalidateGetQuickFilters = async ( + queryClient: QueryClient, + { source }: GetQuickFiltersPathParameters, + options?: InvalidateOptions, +): Promise => { + await queryClient.invalidateQueries( + { queryKey: getGetQuickFiltersQueryKey({ source }) }, + options, + ); + + return queryClient; +}; + +/** + * Replaces the org's quick filters for the source named in the path. + * @summary Update quick filters + */ +export const updateQuickFilters = ( + { source }: UpdateQuickFiltersPathParameters, + quickfiltertypesUpdatableQuickFiltersDTO?: BodyType, + signal?: AbortSignal, +) => { + return GeneratedAPIInstance({ + url: `/api/v2/quick_filters/${source}`, + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + data: quickfiltertypesUpdatableQuickFiltersDTO, + signal, + }); +}; + +export const getUpdateQuickFiltersMutationOptions = < + TError = ErrorType, + TContext = unknown, +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { + pathParams: UpdateQuickFiltersPathParameters; + data?: BodyType; + }, + TContext + >; +}): UseMutationOptions< + Awaited>, + TError, + { + pathParams: UpdateQuickFiltersPathParameters; + data?: BodyType; + }, + TContext +> => { + const mutationKey = ['updateQuickFilters']; + const { mutation: mutationOptions } = options + ? options.mutation && + 'mutationKey' in options.mutation && + options.mutation.mutationKey + ? options + : { ...options, mutation: { ...options.mutation, mutationKey } } + : { mutation: { mutationKey } }; + + const mutationFn: MutationFunction< + Awaited>, + { + pathParams: UpdateQuickFiltersPathParameters; + data?: BodyType; + } + > = (props) => { + const { pathParams, data } = props ?? {}; + + return updateQuickFilters(pathParams, data); + }; + + return { mutationFn, ...mutationOptions }; +}; + +export type UpdateQuickFiltersMutationResult = NonNullable< + Awaited> +>; +export type UpdateQuickFiltersMutationBody = + | BodyType + | undefined; +export type UpdateQuickFiltersMutationError = ErrorType; + +/** + * @summary Update quick filters + */ +export const useUpdateQuickFilters = < + TError = ErrorType, + TContext = unknown, +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { + pathParams: UpdateQuickFiltersPathParameters; + data?: BodyType; + }, + TContext + >; +}): UseMutationResult< + Awaited>, + TError, + { + pathParams: UpdateQuickFiltersPathParameters; + data?: BodyType; + }, + TContext +> => { + return useMutation(getUpdateQuickFiltersMutationOptions(options)); +}; diff --git a/frontend/src/api/generated/services/sigNoz.schemas.ts b/frontend/src/api/generated/services/sigNoz.schemas.ts index b1d5ace6c71..e059724ebca 100644 --- a/frontend/src/api/generated/services/sigNoz.schemas.ts +++ b/frontend/src/api/generated/services/sigNoz.schemas.ts @@ -385,6 +385,38 @@ export interface AlertmanagertypesGoogleChatReceiverConfigDTO { webhook_url?: ConfigSecretURLDTO; } +export type AlertmanagertypesIncidentIOReceiverConfigDTOMetadata = { + [key: string]: string; +}; + +export interface AlertmanagertypesIncidentIOReceiverConfigDTO { + /** + * @type string + */ + description?: string; + http_config?: ConfigHTTPClientConfigDTO; + /** + * @type object + */ + metadata?: AlertmanagertypesIncidentIOReceiverConfigDTOMetadata; + /** + * @type boolean + */ + send_resolved?: boolean; + /** + * @type string + */ + title?: string; + /** + * @type string + */ + token?: string; + /** + * @type string + */ + url?: string; +} + export interface AlertmanagertypesJSMOpsReceiverConfigDTO { /** * @type string @@ -685,39 +717,6 @@ export interface ConfigEmailConfigDTO { to?: string; } -export type TimeDurationDTO = number; - -export interface ConfigURLType2DTO { - [key: string]: unknown; -} - -export interface ConfigIncidentioConfigDTO { - /** - * @type string - */ - alert_source_token?: string; - /** - * @type string - */ - alert_source_token_file?: string; - http_config?: ConfigHTTPClientConfigDTO; - /** - * @type integer - * @minimum 0 - */ - max_alerts?: number; - /** - * @type boolean - */ - send_resolved?: boolean; - timeout?: TimeDurationDTO; - url?: ConfigURLType2DTO; - /** - * @type string - */ - url_file?: string; -} - export interface ConfigMattermostFieldDTO { /** * @type boolean,null @@ -903,6 +902,10 @@ export interface ConfigMSTeamsV2ConfigDTO { webhook_url_file?: string; } +export interface ConfigURLType2DTO { + [key: string]: unknown; +} + export interface ConfigOpsGenieConfigResponderDTO { /** * @type string @@ -1011,6 +1014,8 @@ export interface ConfigPagerdutyLinkDTO { text?: string; } +export type TimeDurationDTO = number; + export type ConfigPagerdutyConfigDTODetails = { [key: string]: unknown }; export interface ConfigPagerdutyConfigDTO { @@ -1672,7 +1677,7 @@ export type AlertmanagertypesPostableChannelDTO = unknown & { /** * @type array */ - incidentio_configs?: ConfigIncidentioConfigDTO[]; + incidentio_configs?: AlertmanagertypesIncidentIOReceiverConfigDTO[]; /** * @type array */ @@ -1803,7 +1808,7 @@ export interface AlertmanagertypesReceiverDTO { /** * @type array */ - incidentio_configs?: ConfigIncidentioConfigDTO[]; + incidentio_configs?: AlertmanagertypesIncidentIOReceiverConfigDTO[]; /** * @type array */ @@ -3300,6 +3305,33 @@ export interface CommonJSONRefDTO { $ref?: string; } +export interface ConfigIncidentioConfigDTO { + /** + * @type string + */ + alert_source_token?: string; + /** + * @type string + */ + alert_source_token_file?: string; + http_config?: ConfigHTTPClientConfigDTO; + /** + * @type integer + * @minimum 0 + */ + max_alerts?: number; + /** + * @type boolean + */ + send_resolved?: boolean; + timeout?: TimeDurationDTO; + url?: ConfigURLType2DTO; + /** + * @type string + */ + url_file?: string; +} + export type ConfigJiraConfigDTOCustomFields = { [key: string]: unknown }; export interface ConfigJiraFieldConfigDTO { @@ -5461,6 +5493,34 @@ export interface FeaturetypesGettableFeatureDTO { variants?: FeaturetypesGettableFeatureDTOVariants; } +export interface GatewaytypesLimitValueDTO { + /** + * @type integer,null + */ + count?: number | null; + /** + * @type integer,null + */ + size?: number | null; +} + +export interface GatewaytypesLimitConfigDTO { + day?: GatewaytypesLimitValueDTO; + second?: GatewaytypesLimitValueDTO; +} + +export interface GatewaytypesDeprecatedPostableIngestionKeyLimitDTO { + config?: GatewaytypesLimitConfigDTO; + /** + * @type string + */ + signal?: string; + /** + * @type array,null + */ + tags?: string[] | null; +} + export interface GatewaytypesGettableCreatedIngestionKeyDTO { /** * @type string @@ -5498,22 +5558,6 @@ export interface GatewaytypesPaginationDTO { total?: number; } -export interface GatewaytypesLimitValueDTO { - /** - * @type integer,null - */ - count?: number | null; - /** - * @type integer,null - */ - size?: number | null; -} - -export interface GatewaytypesLimitConfigDTO { - day?: GatewaytypesLimitValueDTO; - second?: GatewaytypesLimitValueDTO; -} - export interface GatewaytypesLimitMetricValueDTO { /** * @type integer @@ -5631,6 +5675,10 @@ export interface GatewaytypesPostableIngestionKeyDTO { export interface GatewaytypesPostableIngestionKeyLimitDTO { config?: GatewaytypesLimitConfigDTO; + /** + * @type string + */ + keyId: string; /** * @type string */ @@ -8978,6 +9026,47 @@ export enum Querybuildertypesv5QueryTypeDTO { clickhouse_sql = 'clickhouse_sql', promql = 'promql', } +export enum QuickfiltertypesSourceDTO { + traces = 'traces', + logs = 'logs', + api_monitoring = 'api_monitoring', + exceptions = 'exceptions', + meter = 'meter', + ai_observability = 'ai_observability', +} +export interface QuickfiltertypesSourceFiltersDTO { + /** + * @type string + * @format date-time + */ + createdAt?: string; + /** + * @type array + */ + filters: TelemetrytypesTelemetryFieldKeyDTO[]; + /** + * @type string + */ + id: string; + /** + * @type string + */ + orgId: string; + source: QuickfiltertypesSourceDTO; + /** + * @type string + * @format date-time + */ + updatedAt?: string; +} + +export interface QuickfiltertypesUpdatableQuickFiltersDTO { + /** + * @type array + */ + filters: TelemetrytypesTelemetryFieldKeyDTO[]; +} + export interface RenderErrorResponseDTO { error: ErrorsJSONDTO; /** @@ -10790,6 +10879,11 @@ export type GetAIObservabilityFieldsValuesParams = { * @description undefined */ name?: string; + /** + * @type string + * @description undefined + */ + existingQuery?: string; }; export type GetAIObservabilityFieldsValues200 = { @@ -11908,9 +12002,34 @@ export type CreateIngestionKey201 = { export type DeleteIngestionKeyPathParameters = { keyId: string; }; +export type GetIngestionKeyPathParameters = { + keyId: string; +}; +export type GetIngestionKey200 = { + data: GatewaytypesIngestionKeyDTO; + /** + * @type string + */ + status: string; +}; + export type UpdateIngestionKeyPathParameters = { keyId: string; }; +export type GetIngestionKeyLimitsPathParameters = { + keyId: string; +}; +export type GetIngestionKeyLimits200 = { + /** + * @type array,null + */ + data: GatewaytypesLimitDTO[] | null; + /** + * @type string + */ + status: string; +}; + export type CreateIngestionKeyLimitPathParameters = { keyId: string; }; @@ -11954,6 +12073,31 @@ export type SearchIngestionKeys200 = { status: string; }; +export type CreateIngestionLimit201 = { + data: TypesIdentifiableDTO; + /** + * @type string + */ + status: string; +}; + +export type DeleteIngestionLimitPathParameters = { + limitId: string; +}; +export type GetIngestionLimitPathParameters = { + limitId: string; +}; +export type GetIngestionLimit200 = { + data: GatewaytypesLimitDTO; + /** + * @type string + */ + status: string; +}; + +export type UpdateIngestionLimitPathParameters = { + limitId: string; +}; export type Healthz200 = { data: FactoryResponseDTO; /** @@ -12379,6 +12523,31 @@ export type GetPublicDashboardPanelQueryRangeV2200 = { status: string; }; +export type ListQuickFilters200 = { + /** + * @type array + */ + data: QuickfiltertypesSourceFiltersDTO[]; + /** + * @type string + */ + status: string; +}; + +export type GetQuickFiltersPathParameters = { + source: string; +}; +export type GetQuickFilters200 = { + data: QuickfiltertypesSourceFiltersDTO; + /** + * @type string + */ + status: string; +}; + +export type UpdateQuickFiltersPathParameters = { + source: string; +}; export type Readyz200 = { data: FactoryResponseDTO; /** diff --git a/frontend/src/container/AllAlertChannels/__tests__/CreateAlertChannel.test.tsx b/frontend/src/container/AllAlertChannels/__tests__/CreateAlertChannel.test.tsx index 3c57da96205..6c57706d671 100644 --- a/frontend/src/container/AllAlertChannels/__tests__/CreateAlertChannel.test.tsx +++ b/frontend/src/container/AllAlertChannels/__tests__/CreateAlertChannel.test.tsx @@ -2,6 +2,7 @@ import CreateAlertChannels from 'container/CreateAlertChannels'; import { ChannelType } from 'container/CreateAlertChannels/config'; import { GoogleChatInitialConfig, + IncidentIOInitialConfig, JiraInitialConfig, JsmOpsInitialConfig, } from 'container/CreateAlertChannels/defaults'; @@ -585,7 +586,7 @@ describe('Create Alert Channel', () => { description: 'jira_site_invalid', }), ); - }); + }, 15000); it('Should send a jira_configs payload with basic auth', async () => { let requestBody: unknown; @@ -737,6 +738,122 @@ describe('Create Alert Channel', () => { }); }); }); + describe('incident.io', () => { + const incidentIOURL = + 'https://api.incident.io/v2/alert_events/http/01M0D1JNVBGBGVTWX053EM12XV'; + + beforeEach(() => { + render(); + }); + + it('Should display the URL and token fields with the docs tip', () => { + testLabelInputAndHelpValue({ + labelText: 'field_incidentio_url', + testId: 'incidentio-url-textbox', + }); + testLabelInputAndHelpValue({ + labelText: 'field_incidentio_token', + testId: 'incidentio-token-textbox', + }); + expect(screen.getByTestId('incidentio-tip')).toBeInTheDocument(); + expect( + screen.getByRole('link', { name: 'incidentio_tip_link' }), + ).toHaveAttribute( + 'href', + 'https://signoz.io/docs/alerts-management/notification-channel/incidentio/', + ); + }); + + it('Should block save when the URL or token is missing', async () => { + const user = userEvent.setup(); + await user.type( + screen.getByTestId('channel-name-textbox'), + 'incidentio-channel', + ); + + await user.click(screen.getByTestId('save-channel-button')); + + await waitFor(() => + expect(errorNotification).toHaveBeenCalledWith({ + message: 'Error', + description: 'incidentio_required_fields', + }), + ); + }); + + it('Should display an error when the URL is not an alert events URL', async () => { + const user = userEvent.setup(); + await user.type( + screen.getByTestId('channel-name-textbox'), + 'incidentio-channel', + ); + await user.type( + screen.getByTestId('incidentio-url-textbox'), + 'https://api.incident.io/v2/incidents', + ); + await user.type(screen.getByTestId('incidentio-token-textbox'), 'tok-abc'); + + await user.click(screen.getByTestId('save-channel-button')); + + await waitFor(() => + expect(errorNotification).toHaveBeenCalledWith({ + message: 'Error', + description: 'incidentio_url_invalid', + }), + ); + }, 15000); + + it('Should send an incidentio_configs payload with prefilled defaults', async () => { + let requestBody: unknown; + server.use( + rest.post('http://localhost/api/v1/channels', async (req, res, ctx) => { + requestBody = await req.json(); + return res( + ctx.status(201), + ctx.json({ status: 'success', data: 'channel created' }), + ); + }), + ); + + const user = userEvent.setup(); + await user.type( + screen.getByTestId('channel-name-textbox'), + 'incidentio-channel', + ); + await user.type( + screen.getByTestId('incidentio-url-textbox'), + incidentIOURL, + ); + await user.type(screen.getByTestId('incidentio-token-textbox'), 'tok-abc'); + + await user.click(screen.getByTestId('incidentio-metadata-add')); + await user.type(screen.getByTestId('incidentio-metadata-key-0'), 'team'); + await user.type(screen.getByTestId('incidentio-metadata-value-0'), 'core'); + + await user.click(screen.getByTestId('save-channel-button')); + + await waitFor(() => + expect(successNotification).toHaveBeenCalledWith({ + message: 'Success', + description: 'channel_creation_done', + }), + ); + + expect(requestBody).toStrictEqual({ + name: 'incidentio-channel', + incidentio_configs: [ + { + url: incidentIOURL, + token: 'tok-abc', + send_resolved: true, + title: IncidentIOInitialConfig.title, + description: IncidentIOInitialConfig.description, + metadata: { team: 'core' }, + }, + ], + }); + }, 15000); + }); describe('Changing the channel type', () => { async function selectType( user: ReturnType, diff --git a/frontend/src/container/AllAlertChannels/__tests__/EditAlertChannelSave.test.tsx b/frontend/src/container/AllAlertChannels/__tests__/EditAlertChannelSave.test.tsx index fe4326ea059..fe05a54a0c0 100644 --- a/frontend/src/container/AllAlertChannels/__tests__/EditAlertChannelSave.test.tsx +++ b/frontend/src/container/AllAlertChannels/__tests__/EditAlertChannelSave.test.tsx @@ -90,6 +90,40 @@ describe('EditAlertChannels save', () => { await waitFor(() => expect(edit.calls).toHaveLength(1)); }); + it('sends an incidentio_configs payload when editing an incident.io channel', async () => { + const edit = mockEditChannel(); + render( + , + ); + + const user = userEvent.setup(); + await user.click(screen.getByTestId('save-channel-button')); + + await waitFor(() => expect(edit.calls).toHaveLength(1)); + expect(edit.calls[0].id).toBe('4'); + expect(edit.calls[0].body).toStrictEqual({ + name: 'incidentio-channel', + incidentio_configs: [ + { + url: 'https://api.incident.io/v2/alert_events/http/01M0D1JNVBGBGVTWX053EM12XV', + token: 'tok-abc', + send_resolved: true, + metadata: { env: 'prod' }, + }, + ], + }); + }); + it('persists send_resolved toggle in the edit request', async () => { const edit = mockEditChannel(); render( diff --git a/frontend/src/container/CreateAlertChannels/config.ts b/frontend/src/container/CreateAlertChannels/config.ts index ce8a443f1b9..67d5e5e6fb7 100644 --- a/frontend/src/container/CreateAlertChannels/config.ts +++ b/frontend/src/container/CreateAlertChannels/config.ts @@ -107,6 +107,7 @@ export enum ChannelType { GoogleChat = 'googlechat', Jira = 'jira', JsmOps = 'jsmops', + IncidentIO = 'incidentio', } // LabelFilterStatement will be used for preparing filter conditions / matchers @@ -159,6 +160,22 @@ export interface JiraChannel extends Channel { reopen_duration?: string; } +// IncidentIOChannel configures the incident.io alert channel, backed by an +// incident.io HTTP alert source (Alert Events V2 API). +export interface IncidentIOChannel extends Channel { + // per-source alert events URL, e.g. + // https://api.incident.io/v2/alert_events/http/ + url: string; + // the alert source's secret token + token: string; + // alert title template + title?: string; + // alert body template (markdown, rendered natively by incident.io) + description?: string; + // extra metadata pairs merged over the alert's labels (channel wins on clash) + metadata?: Record; +} + // JsmOpsChannel configures the Jira Service Management Ops alert channel // (ex-Opsgenie alert API). Auth is the JSM integration API key. export interface JsmOpsChannel extends Channel { diff --git a/frontend/src/container/CreateAlertChannels/defaults.ts b/frontend/src/container/CreateAlertChannels/defaults.ts index e15fe36e1e4..dda8238e63e 100644 --- a/frontend/src/container/CreateAlertChannels/defaults.ts +++ b/frontend/src/container/CreateAlertChannels/defaults.ts @@ -2,6 +2,7 @@ import { ChannelType, EmailChannel, GoogleChatChannel, + IncidentIOChannel, JiraChannel, JsmOpsChannel, MsTeamsChannel, @@ -144,6 +145,29 @@ export const JsmOpsInitialConfig: Partial = { tags: ['signoz-alert'], }; +// mirrors DefaultIncidentIOTitleTemplate / DefaultIncidentIODescriptionTemplate +// in pkg/types/alertmanagertypes/incidentio.go, applied by the backend when +// title / description are left empty. send_resolved is seeded on so incident.io +// alerts resolve with the rule (the backend cannot default it). +export const IncidentIOInitialConfig: Partial = { + send_resolved: true, + title: `[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }}`, + description: `{{ 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 }}{{ if .GeneratorURL }}[View in SigNoz]({{ .GeneratorURL }}) + +{{ end }}{{ if .Annotations.related_logs }}[View related logs]({{ .Annotations.related_logs }}) + +{{ end }}{{ if .Annotations.related_traces }}[View related traces]({{ .Annotations.related_traces }}) + +{{ end }}{{ end }}`, +}; + export const EmailInitialConfig: Partial = { send_resolved: true, html: `