Skip to content

Commit f0bfe78

Browse files
gaobinlongdakrone
authored andcommitted
Don't dump a stacktrace for invalid patterns when executing elasticsearch-croneval (#49744)
1 parent 4441a22 commit f0bfe78

File tree

2 files changed

+60
-36
lines changed

2 files changed

+60
-36
lines changed

docs/reference/commands/croneval.asciidoc

+5-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ This command is provided in the `$ES_HOME/bin` directory.
3030
`-c, --count` <Integer>::
3131
The number of future times this expression will be triggered. The default
3232
value is `10`.
33-
33+
34+
`-d, --detail`::
35+
Shows detail for invalid cron expression. It will print the stacktrace if the
36+
expression is not valid.
37+
3438
`-h, --help`::
3539
Returns all of the command parameters.
3640

x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/tool/CronEvalTool.java

+55-35
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,16 @@ public static void main(String[] args) throws Exception {
3737

3838
private final OptionSpec<Integer> countOption;
3939
private final OptionSpec<String> arguments;
40+
private final OptionSpec<Void> detailOption;
4041

4142
CronEvalTool() {
4243
super("Validates and evaluates a cron expression");
43-
this.countOption = parser.acceptsAll(Arrays.asList("c", "count"),
44-
"The number of future times this expression will be triggered")
45-
.withRequiredArg().ofType(Integer.class).defaultsTo(10);
44+
this.countOption = parser.acceptsAll(Arrays.asList("c", "count"), "The number of future times this expression will be triggered")
45+
.withRequiredArg()
46+
.ofType(Integer.class)
47+
.defaultsTo(10);
4648
this.arguments = parser.nonOptions("expression");
49+
this.detailOption = parser.acceptsAll(Arrays.asList("d", "detail"), "Show detail for invalid cron expression");
4750

4851
parser.accepts("E", "Unused. Only for compatibility with other CLI tools.").withRequiredArg();
4952
}
@@ -55,46 +58,63 @@ protected void execute(Terminal terminal, OptionSet options) throws Exception {
5558
if (args.size() != 1) {
5659
throw new UserException(ExitCodes.USAGE, "expecting a single argument that is the cron expression to evaluate");
5760
}
58-
execute(terminal, args.get(0), count);
61+
boolean printDetail = options.has(detailOption);
62+
execute(terminal, args.get(0), count, printDetail);
5963
}
6064

61-
private void execute(Terminal terminal, String expression, int count) throws Exception {
62-
Cron.validate(expression);
63-
terminal.println("Valid!");
65+
private void execute(Terminal terminal, String expression, int count, boolean printDetail) throws Exception {
66+
try {
67+
Cron.validate(expression);
68+
terminal.println("Valid!");
6469

65-
final ZonedDateTime date = ZonedDateTime.now(ZoneOffset.UTC);
66-
final boolean isLocalTimeUTC = UTC_FORMATTER.zone().equals(LOCAL_FORMATTER.zone());
67-
if (isLocalTimeUTC) {
68-
terminal.println("Now is [" + UTC_FORMATTER.format(date) + "] in UTC");
69-
} else {
70-
terminal.println("Now is [" + UTC_FORMATTER.format(date) + "] in UTC, local time is [" + LOCAL_FORMATTER.format(date) + "]");
70+
final ZonedDateTime date = ZonedDateTime.now(ZoneOffset.UTC);
71+
final boolean isLocalTimeUTC = UTC_FORMATTER.zone().equals(LOCAL_FORMATTER.zone());
72+
if (isLocalTimeUTC) {
73+
terminal.println("Now is [" + UTC_FORMATTER.format(date) + "] in UTC");
74+
} else {
75+
terminal.println(
76+
"Now is [" + UTC_FORMATTER.format(date) + "] in UTC, local time is [" + LOCAL_FORMATTER.format(date) + "]"
77+
);
7178

72-
}
73-
terminal.println("Here are the next " + count + " times this cron expression will trigger:");
74-
75-
Cron cron = new Cron(expression);
76-
long time = date.toInstant().toEpochMilli();
77-
78-
for (int i = 0; i < count; i++) {
79-
long prevTime = time;
80-
time = cron.getNextValidTimeAfter(time);
81-
if (time < 0) {
82-
if (i == 0) {
83-
throw new UserException(ExitCodes.OK, "Could not compute future times since ["
84-
+ UTC_FORMATTER.format(Instant.ofEpochMilli(prevTime)) + "] " + "(perhaps the cron expression only points to " +
85-
"times in the" +
86-
" " +
87-
"past?)");
88-
}
89-
break;
9079
}
80+
terminal.println("Here are the next " + count + " times this cron expression will trigger:");
81+
82+
Cron cron = new Cron(expression);
83+
long time = date.toInstant().toEpochMilli();
84+
85+
for (int i = 0; i < count; i++) {
86+
long prevTime = time;
87+
time = cron.getNextValidTimeAfter(time);
88+
if (time < 0) {
89+
if (i == 0) {
90+
throw new UserException(
91+
ExitCodes.OK,
92+
"Could not compute future times since ["
93+
+ UTC_FORMATTER.format(Instant.ofEpochMilli(prevTime))
94+
+ "] "
95+
+ "(perhaps the cron expression only points to "
96+
+ "times in the"
97+
+ " "
98+
+ "past?)"
99+
);
100+
}
101+
break;
102+
}
91103

92-
if (isLocalTimeUTC) {
93-
terminal.println((i + 1) + ".\t" + UTC_FORMATTER.format(Instant.ofEpochMilli(time)));
104+
if (isLocalTimeUTC) {
105+
terminal.println((i + 1) + ".\t" + UTC_FORMATTER.format(Instant.ofEpochMilli(time)));
106+
} else {
107+
terminal.println((i + 1) + ".\t" + UTC_FORMATTER.format(Instant.ofEpochMilli(time)));
108+
terminal.println("\t" + LOCAL_FORMATTER.format(Instant.ofEpochMilli(time)));
109+
}
110+
}
111+
} catch (Exception e) {
112+
if (printDetail) {
113+
throw e;
94114
} else {
95-
terminal.println((i + 1) + ".\t" + UTC_FORMATTER.format(Instant.ofEpochMilli(time)));
96-
terminal.println("\t" + LOCAL_FORMATTER.format(Instant.ofEpochMilli(time)));
115+
throw new UserException(ExitCodes.OK, e.getMessage() + (e.getCause() == null ? "" : ": " + e.getCause().getMessage()));
97116
}
117+
98118
}
99119
}
100120
}

0 commit comments

Comments
 (0)