Skip to content

Commit f3ed01d

Browse files
committed
[Improvement][alert] Add configurable timeout for script alert plugin (#18034)
1 parent b12b682 commit f3ed01d

File tree

7 files changed

+73
-8
lines changed

7 files changed

+73
-8
lines changed

dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtils.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.dolphinscheduler.plugin.alert.script;
1919

2020
import java.io.IOException;
21+
import java.util.concurrent.TimeUnit;
2122

2223
import lombok.extern.slf4j.Slf4j;
2324

@@ -29,12 +30,13 @@ private ProcessUtils() {
2930
}
3031

3132
/**
32-
* executeScript
33+
* executeScript with timeout
3334
*
35+
* @param timeoutSeconds timeout in seconds, if <= 0 waits indefinitely
3436
* @param cmd cmd params
35-
* @return exit code
37+
* @return exit code, -1 if error, -2 if timeout
3638
*/
37-
static Integer executeScript(String... cmd) {
39+
static Integer executeScript(long timeoutSeconds, String... cmd) {
3840

3941
int exitCode = -1;
4042

@@ -46,7 +48,16 @@ static Integer executeScript(String... cmd) {
4648

4749
inputStreamGobbler.start();
4850
errorStreamGobbler.start();
49-
return process.waitFor();
51+
52+
boolean finished = process.waitFor(timeoutSeconds, TimeUnit.SECONDS);
53+
if (!finished) {
54+
log.error("script execution timed out after {} seconds, destroying process", timeoutSeconds);
55+
process.destroyForcibly();
56+
inputStreamGobbler.interrupt();
57+
errorStreamGobbler.interrupt();
58+
return -2;
59+
}
60+
return process.exitValue();
5061
} catch (IOException | InterruptedException e) {
5162
log.error("execute alert script error {}", e.getMessage());
5263
Thread.currentThread().interrupt();

dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactory.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
2222
import org.apache.dolphinscheduler.alert.api.AlertInputTips;
2323
import org.apache.dolphinscheduler.common.utils.JSONUtils;
24+
import org.apache.dolphinscheduler.spi.params.base.DataType;
2425
import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
2526
import org.apache.dolphinscheduler.spi.params.base.PluginParams;
2627
import org.apache.dolphinscheduler.spi.params.base.Validate;
2728
import org.apache.dolphinscheduler.spi.params.input.InputParam;
29+
import org.apache.dolphinscheduler.spi.params.input.number.InputNumberParam;
2830
import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
2931

3032
import java.util.Arrays;
@@ -66,7 +68,17 @@ public List<PluginParams> params() {
6668
.addValidate(Validate.newBuilder().setRequired(true).build())
6769
.build();
6870

69-
return Arrays.asList(scriptUserParam, scriptPathParam, scriptTypeParams);
71+
InputNumberParam scriptTimeoutParam =
72+
InputNumberParam.newBuilder(ScriptParamsConstants.NAME_SCRIPT_TIMEOUT,
73+
ScriptParamsConstants.SCRIPT_TIMEOUT)
74+
.setValue(ScriptParamsConstants.DEFAULT_SCRIPT_TIMEOUT)
75+
.addValidate(Validate.newBuilder()
76+
.setType(DataType.NUMBER.getDataType())
77+
.setRequired(false)
78+
.build())
79+
.build();
80+
81+
return Arrays.asList(scriptUserParam, scriptPathParam, scriptTypeParams, scriptTimeoutParam);
7082
}
7183

7284
@Override

dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptParamsConstants.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ public final class ScriptParamsConstants {
3131

3232
static final String NAME_SCRIPT_USER_PARAMS = "userParams";
3333

34+
static final String SCRIPT_TIMEOUT = "$t('timeout')";
35+
36+
static final String NAME_SCRIPT_TIMEOUT = "timeout";
37+
38+
static final int DEFAULT_SCRIPT_TIMEOUT = 60;
39+
3440
private ScriptParamsConstants() {
3541
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
3642
}

dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSender.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public final class ScriptSender {
3636
private final String scriptPath;
3737
private final String scriptType;
3838
private final String userParams;
39+
private final long timeout;
3940

4041
ScriptSender(Map<String, String> config) {
4142
scriptPath = StringUtils.isNotBlank(config.get(ScriptParamsConstants.NAME_SCRIPT_PATH))
@@ -47,6 +48,9 @@ public final class ScriptSender {
4748
userParams = StringUtils.isNotBlank(config.get(ScriptParamsConstants.NAME_SCRIPT_USER_PARAMS))
4849
? config.get(ScriptParamsConstants.NAME_SCRIPT_USER_PARAMS)
4950
: "";
51+
timeout = StringUtils.isNotBlank(config.get(ScriptParamsConstants.NAME_SCRIPT_TIMEOUT))
52+
? Long.parseLong(config.get(ScriptParamsConstants.NAME_SCRIPT_TIMEOUT))
53+
: ScriptParamsConstants.DEFAULT_SCRIPT_TIMEOUT;
5054
}
5155

5256
AlertResult sendScriptAlert(String title, String content) {
@@ -108,13 +112,19 @@ private AlertResult executeShellScript(String title, String content) {
108112

109113
String[] cmd = {"/bin/sh", "-c", scriptPath + ALERT_TITLE_OPTION + "'" + title + "'" + ALERT_CONTENT_OPTION
110114
+ "'" + content + "'" + ALERT_USER_PARAMS_OPTION + "'" + userParams + "'"};
111-
int exitCode = ProcessUtils.executeScript(cmd);
115+
int exitCode = ProcessUtils.executeScript(timeout, cmd);
112116

113117
if (exitCode == 0) {
114118
alertResult.setSuccess(true);
115119
alertResult.setMessage("send script alert msg success");
116120
return alertResult;
117121
}
122+
if (exitCode == -2) {
123+
alertResult.setMessage("send script alert msg error, script execution timed out after " + timeout
124+
+ " seconds");
125+
log.error("send script alert msg error, script execution timed out after {} seconds", timeout);
126+
return alertResult;
127+
}
118128
alertResult.setMessage("send script alert msg error,exitCode is " + exitCode);
119129
log.info("send script alert msg error,exitCode is {}", exitCode);
120130
return alertResult;

dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtilsTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717

1818
package org.apache.dolphinscheduler.plugin.alert.script;
1919

20+
import org.junit.jupiter.api.Assertions;
2021
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.condition.DisabledOnOs;
23+
import org.junit.jupiter.api.condition.OS;
2124

2225
/**
2326
* ProcessUtilsTest
@@ -33,7 +36,15 @@ public class ProcessUtilsTest {
3336

3437
@Test
3538
public void testExecuteScript() {
36-
int code = ProcessUtils.executeScript(cmd);
39+
int code = ProcessUtils.executeScript(60, cmd);
3740
assert code != -1;
3841
}
42+
43+
@Test
44+
@DisabledOnOs(OS.WINDOWS)
45+
public void testExecuteScriptTimeout() {
46+
String[] sleepCmd = {"/bin/sh", "-c", "sleep 30"};
47+
int code = ProcessUtils.executeScript(2, sleepCmd);
48+
Assertions.assertEquals(-2, code);
49+
}
3950
}

dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactoryTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class ScriptAlertChannelFactoryTest {
3434
public void testGetParams() {
3535
ScriptAlertChannelFactory scriptAlertChannelFactory = new ScriptAlertChannelFactory();
3636
List<PluginParams> params = scriptAlertChannelFactory.params();
37-
Assertions.assertEquals(3, params.size());
37+
Assertions.assertEquals(4, params.size());
3838
}
3939

4040
@Test

dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSenderTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,19 @@ public void testTypeIsError() {
100100
assertFalse(alertResult.isSuccess());
101101
}
102102

103+
@Test
104+
public void testDefaultTimeout() {
105+
ScriptSender scriptSender = new ScriptSender(scriptConfig);
106+
AlertResult alertResult = scriptSender.sendScriptAlert("test title Kris", "test content");
107+
Assertions.assertTrue(alertResult.isSuccess());
108+
}
109+
110+
@Test
111+
public void testCustomTimeout() {
112+
scriptConfig.put(ScriptParamsConstants.NAME_SCRIPT_TIMEOUT, "30");
113+
ScriptSender scriptSender = new ScriptSender(scriptConfig);
114+
AlertResult alertResult = scriptSender.sendScriptAlert("test title Kris", "test content");
115+
Assertions.assertTrue(alertResult.isSuccess());
116+
}
117+
103118
}

0 commit comments

Comments
 (0)