From eda420d118f7ef7cc99fbf357625664c1ef41611 Mon Sep 17 00:00:00 2001 From: NekoPunch <95899648+orangeCatDeveloper@users.noreply.github.com> Date: Tue, 25 Aug 2026 21:13:20 -0700 Subject: [PATCH] [fix] allow long threshold expr when binding many monitors (#4330) --- .../common/entity/alerter/AlertDefine.java | 4 +- .../entity/alerter/AlertDefineTest.java | 72 +++++++++++++++++++ .../db/migration/h2/V183__update_column.sql | 19 +++++ .../migration/mysql/V183__update_column.sql | 50 +++++++++++++ .../postgresql/V183__update_column.sql | 20 ++++++ 5 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 hertzbeat-common-spring/src/test/java/org/apache/hertzbeat/common/entity/alerter/AlertDefineTest.java create mode 100644 hertzbeat-startup/src/main/resources/db/migration/h2/V183__update_column.sql create mode 100644 hertzbeat-startup/src/main/resources/db/migration/mysql/V183__update_column.sql create mode 100644 hertzbeat-startup/src/main/resources/db/migration/postgresql/V183__update_column.sql diff --git a/hertzbeat-common-spring/src/main/java/org/apache/hertzbeat/common/entity/alerter/AlertDefine.java b/hertzbeat-common-spring/src/main/java/org/apache/hertzbeat/common/entity/alerter/AlertDefine.java index a0dd83cc7d..7ad8747dc0 100644 --- a/hertzbeat-common-spring/src/main/java/org/apache/hertzbeat/common/entity/alerter/AlertDefine.java +++ b/hertzbeat-common-spring/src/main/java/org/apache/hertzbeat/common/entity/alerter/AlertDefine.java @@ -69,8 +69,8 @@ public class AlertDefine { private String type; @Schema(title = "Alarm Threshold Expr", example = "usage>90", accessMode = READ_WRITE) - @Size(max = 2048) - @Column(length = 2048) + @Size(max = 65535) + @Column(columnDefinition = "TEXT") private String expr; @Schema(title = "Execution Period/ Window Size (seconds) - For periodic rules/ For log realtime", example = "300") diff --git a/hertzbeat-common-spring/src/test/java/org/apache/hertzbeat/common/entity/alerter/AlertDefineTest.java b/hertzbeat-common-spring/src/test/java/org/apache/hertzbeat/common/entity/alerter/AlertDefineTest.java new file mode 100644 index 0000000000..dbf7af9e8c --- /dev/null +++ b/hertzbeat-common-spring/src/test/java/org/apache/hertzbeat/common/entity/alerter/AlertDefineTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.common.entity.alerter; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import jakarta.validation.ValidatorFactory; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.LongStream; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Test case for {@link AlertDefine} + */ +class AlertDefineTest { + + private final ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + private final Validator validator = factory.getValidator(); + + @Test + void exprShouldAllowBindingManyMonitors() { + String boundMonitors = LongStream.range(0, 76) + .mapToObj(id -> "equals(__instance__, \"" + (653868108767488L + id) + "\")") + .collect(Collectors.joining(" or ")); + String expr = "equals(__app__,\"ping\") && equals(__available__,\"down\") && (" + boundMonitors + ")"; + assertTrue(expr.length() > 2048); + + AlertDefine define = AlertDefine.builder() + .name("ping-offline") + .type("realtime_metric") + .expr(expr) + .template("instance {{ $labels.instance }} is offline") + .build(); + + Set> violations = validator.validate(define); + assertTrue(violations.isEmpty(), "binding many monitors should not fail validation: " + violations); + } + + @Test + void oversizedExprShouldReportCharacterLength() { + AlertDefine define = AlertDefine.builder() + .name("ping-offline") + .type("realtime_metric") + .expr("x".repeat(65536)) + .template("template") + .build(); + + Set> violations = validator.validate(define); + assertEquals(1, violations.size()); + assertEquals("expr", violations.iterator().next().getPropertyPath().toString()); + } +} diff --git a/hertzbeat-startup/src/main/resources/db/migration/h2/V183__update_column.sql b/hertzbeat-startup/src/main/resources/db/migration/h2/V183__update_column.sql new file mode 100644 index 0000000000..936fbf6547 --- /dev/null +++ b/hertzbeat-startup/src/main/resources/db/migration/h2/V183__update_column.sql @@ -0,0 +1,19 @@ +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. + +-- Enlarge alert define expr to fit rules binding many monitors (#4171) +ALTER TABLE HZB_ALERT_DEFINE ALTER COLUMN expr CLOB; diff --git a/hertzbeat-startup/src/main/resources/db/migration/mysql/V183__update_column.sql b/hertzbeat-startup/src/main/resources/db/migration/mysql/V183__update_column.sql new file mode 100644 index 0000000000..aeb22f273a --- /dev/null +++ b/hertzbeat-startup/src/main/resources/db/migration/mysql/V183__update_column.sql @@ -0,0 +1,50 @@ +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. + +-- Enlarge alert define expr to fit rules binding many monitors (#4171) +DELIMITER // + +CREATE PROCEDURE ModifyAlertDefineExprColumn() +BEGIN + DECLARE table_exists INT; + DECLARE col_exists INT; + + SELECT COUNT(*) INTO table_exists + FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_alert_define'; + + IF table_exists = 1 THEN + SELECT COUNT(*) INTO col_exists + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'hzb_alert_define' + AND COLUMN_NAME = 'expr' + AND DATA_TYPE != 'longtext'; + + IF col_exists = 1 THEN + ALTER TABLE hzb_alert_define MODIFY COLUMN expr LONGTEXT; + END IF; + END IF; +END // + +DELIMITER ; + +CALL ModifyAlertDefineExprColumn(); + +DROP PROCEDURE IF EXISTS ModifyAlertDefineExprColumn; + +COMMIT; diff --git a/hertzbeat-startup/src/main/resources/db/migration/postgresql/V183__update_column.sql b/hertzbeat-startup/src/main/resources/db/migration/postgresql/V183__update_column.sql new file mode 100644 index 0000000000..08c429718e --- /dev/null +++ b/hertzbeat-startup/src/main/resources/db/migration/postgresql/V183__update_column.sql @@ -0,0 +1,20 @@ +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. + +-- Enlarge alert define expr to fit rules binding many monitors (#4171) +ALTER TABLE HZB_ALERT_DEFINE ALTER COLUMN expr TYPE TEXT; +commit;