import {z} from 'zod' export type AlertKind = 'Alert'; export type AlertMetadataV3 = {name: string, appInstance?: string | undefined, group?: string | undefined, user?: string | undefined}; export type Operator = 'GreaterThan' | 'GreaterThanOrEqual' | 'LessThan' | 'LessThanOrEqual' | 'NotEqual'; export type BrokerMetricType = 'MessageIn' | 'MessageOut' | 'MessageSize' | 'OfflinePartitionCount' | 'PartitionCount' | 'UnderMinIsrPartitionCount' | 'UnderReplicatedPartitionCount'; export type Email1 = {to: string, subject: string, body?: string | undefined, type: 'Email'}; export type Slack1 = {channel: string, type: 'Slack'}; export type Teams = {url: string, type: 'Teams'}; export type HttpMethod = 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT'; export type MapString = {[key: string]: string}; export type Basic = {username: string, password: string, type: 'Basic'}; export type Bearer = {token: string, type: 'Bearer'}; export type HttpAuthentification = Basic | Bearer; export type Webhook = {url: string, method: HttpMethod, headers?: MapString | undefined, authentification?: HttpAuthentification | undefined, body?: string | undefined, type: 'Webhook'}; export type Destination = Email1 | Slack1 | Teams | Webhook; export type BrokerAlertV3 = {cluster: string, threshold: number, operator: Operator, metric: BrokerMetricType, description?: string | undefined, displayName?: string | undefined, destination?: Destination | undefined, disable?: boolean | undefined, type: 'BrokerAlert'}; export type ConsumerGroupMetricType = 'OffsetLag' | 'TimeLag'; export type ConsumerGroupAlertV3 = {cluster: string, consumerGroupName: string, threshold: number, operator: Operator, metric: ConsumerGroupMetricType, description?: string | undefined, displayName?: string | undefined, destination?: Destination | undefined, disable?: boolean | undefined, topicName?: string | undefined, type: 'ConsumerGroupAlert'}; export type DataQualityPolicyAlertV3 = {policyName: string, triggerAfter: number, withinInSeconds: number, description?: string | undefined, displayName?: string | undefined, destination?: Destination | undefined, disable?: boolean | undefined, type: 'DataQualityPolicyAlert'}; export type KafkaConnectMetricType = 'FailedTaskCount'; export type KafkaConnectAlertV3 = {cluster: string, connectName: string, connectorName: string, threshold: number, operator: Operator, metric: KafkaConnectMetricType, description?: string | undefined, displayName?: string | undefined, destination?: Destination | undefined, disable?: boolean | undefined, type: 'KafkaConnectAlert'}; export type TopicMetricType = 'MessageCount' | 'MessageIn' | 'MessageOut' | 'MessageSize'; export type TopicAlertV3 = {cluster: string, topicName: string, threshold: number, operator: Operator, metric: TopicMetricType, description?: string | undefined, displayName?: string | undefined, destination?: Destination | undefined, disable?: boolean | undefined, type: 'TopicAlert'}; export type AlertSpecV3 = BrokerAlertV3 | ConsumerGroupAlertV3 | DataQualityPolicyAlertV3 | KafkaConnectAlertV3 | TopicAlertV3; export type AlertResourceV3 = {apiVersion: string, kind: AlertKind, metadata: AlertMetadataV3, spec: AlertSpecV3}; export type CreateApiPublicMonitoringV3AlertArgs = {appInstance?: string | undefined, group?: string | undefined, user?: string | undefined, body: AlertResourceV3}; export type CreateApiPublicMonitoringV3AlertOptions = {baseUrl: string, httpAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const alertKind = z.literal("Alert"); export const alertMetadataV3 = z.object({name: z.string(), appInstance: z.string().optional(), group: z.string().optional(), user: z.string().optional()}); export const operator = z.enum(["GreaterThan", "GreaterThanOrEqual", "LessThan", "LessThanOrEqual", "NotEqual"]); export const brokerMetricType = z.enum(["MessageIn", "MessageOut", "MessageSize", "OfflinePartitionCount", "PartitionCount", "UnderMinIsrPartitionCount", "UnderReplicatedPartitionCount"]); export const email1 = z.object({to: z.string(), subject: z.string(), body: z.string().optional(), type: z.literal("Email")}); export const slack1 = z.object({channel: z.string(), type: z.literal("Slack")}); export const teams = z.object({url: z.string(), type: z.literal("Teams")}); export const httpMethod = z.enum(["DELETE", "GET", "PATCH", "POST", "PUT"]); export const mapString = z.record(z.string(), z.string()); export const basic = z.object({username: z.string(), password: z.string(), type: z.literal("Basic")}); export const bearer = z.object({token: z.string(), type: z.literal("Bearer")}); export const httpAuthentification = z.discriminatedUnion("type", [basic, bearer]); export const webhook = z.object({url: z.string(), method: httpMethod, headers: mapString.optional(), authentification: httpAuthentification.optional(), body: z.string().optional(), type: z.literal("Webhook")}); export const destination = z.discriminatedUnion("type", [email1, slack1, teams, webhook]); export const brokerAlertV3 = z.object({cluster: z.string(), threshold: z.number().int(), operator: operator, metric: brokerMetricType, description: z.string().optional(), displayName: z.string().optional(), destination: destination.optional(), disable: z.boolean().optional(), type: z.literal("BrokerAlert")}); export const consumerGroupMetricType = z.enum(["OffsetLag", "TimeLag"]); export const consumerGroupAlertV3 = z.object({cluster: z.string(), consumerGroupName: z.string(), threshold: z.number().int(), operator: operator, metric: consumerGroupMetricType, description: z.string().optional(), displayName: z.string().optional(), destination: destination.optional(), disable: z.boolean().optional(), topicName: z.string().optional(), type: z.literal("ConsumerGroupAlert")}); export const dataQualityPolicyAlertV3 = z.object({policyName: z.string(), triggerAfter: z.number().int().gt(0), withinInSeconds: z.number().int().gt(0), description: z.string().optional(), displayName: z.string().optional(), destination: destination.optional(), disable: z.boolean().optional(), type: z.literal("DataQualityPolicyAlert")}); export const kafkaConnectMetricType = z.literal("FailedTaskCount"); export const kafkaConnectAlertV3 = z.object({cluster: z.string(), connectName: z.string(), connectorName: z.string(), threshold: z.number().int(), operator: operator, metric: kafkaConnectMetricType, description: z.string().optional(), displayName: z.string().optional(), destination: destination.optional(), disable: z.boolean().optional(), type: z.literal("KafkaConnectAlert")}); export const topicMetricType = z.enum(["MessageCount", "MessageIn", "MessageOut", "MessageSize"]); export const topicAlertV3 = z.object({cluster: z.string(), topicName: z.string(), threshold: z.number().int(), operator: operator, metric: topicMetricType, description: z.string().optional(), displayName: z.string().optional(), destination: destination.optional(), disable: z.boolean().optional(), type: z.literal("TopicAlert")}); export const alertSpecV3 = z.discriminatedUnion("type", [brokerAlertV3, consumerGroupAlertV3, dataQualityPolicyAlertV3, kafkaConnectAlertV3, topicAlertV3]); export const alertResourceV3 = z.object({apiVersion: z.string(), kind: alertKind, metadata: alertMetadataV3, spec: alertSpecV3}); export const createResult = z.enum(["AlreadyExist", "Created"]); export const alertCreateResultV3 = z.object({resource: alertResourceV3, createResult: createResult}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Create a Alert * * POST /public/monitoring/v3/alert */ export const createApiPublicMonitoringV3Alert = async (args: CreateApiPublicMonitoringV3AlertArgs, options: CreateApiPublicMonitoringV3AlertOptions) => { const {baseUrl, fetch: fetchFn = fetch, httpAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (args.appInstance != null) query.append("appInstance", String(args.appInstance)) if (args.group != null) query.append("group", String(args.group)) if (args.user != null) query.append("user", String(args.user)) if (httpAuth !== undefined) headers.set('authorization', `Bearer ${httpAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/public/monitoring/v3/alert${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(alertCreateResultV3, await res.json()) };