forked from AutohomeCorp/frostmourne
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
prometheus增加/api/v1/query_range查询监控
- Loading branch information
kcq
committed
Oct 9, 2022
1 parent
0de0e5b
commit 71e2bf0
Showing
21 changed files
with
667 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
161 changes: 161 additions & 0 deletions
161
frostmourne-common/src/main/java/com/autohome/frostmourne/common/time/TimeParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
package com.autohome.frostmourne.common.time; | ||
|
||
/** | ||
* description | ||
* | ||
* @author kechangqing | ||
* @since 2022/9/30 16:47 | ||
*/ | ||
public class TimeParser { | ||
|
||
private static final int PREVIOUS_OP = -1; | ||
|
||
TimeToken token; | ||
TimeScanner scanner; | ||
TimeSpec spec; | ||
|
||
int op = TimeToken.PLUS; | ||
int prevMultiplier = -1; | ||
|
||
public TimeParser(String dateString) { | ||
scanner = new TimeScanner(dateString); | ||
spec = new TimeSpec(dateString); | ||
} | ||
|
||
private void expectToken(int desired, String errorMessage) { | ||
token = scanner.nextToken(); | ||
if (token.id != desired) { | ||
throw new RuntimeException(errorMessage); | ||
} | ||
} | ||
|
||
private void plusMinus(int doop) { | ||
if (doop >= 0) { | ||
op = doop; | ||
expectToken(TimeToken.NUMBER, "There should be number after " + | ||
(op == TimeToken.PLUS ? '+' : '-')); | ||
//reset months-minutes guessing mechanics | ||
prevMultiplier = -1; | ||
} | ||
int delta = Integer.parseInt(token.value); | ||
token = scanner.nextToken(); | ||
prevMultiplier = token.id; | ||
delta *= (op == TimeToken.PLUS) ? +1 : -1; | ||
switch (token.id) { | ||
case TimeToken.YEARS: | ||
spec.dyear += delta; | ||
break; | ||
case TimeToken.MONTHS: | ||
spec.dmonth += delta; | ||
break; | ||
case TimeToken.WEEKS: | ||
delta *= 7; | ||
spec.dday += delta; | ||
break; | ||
case TimeToken.DAYS: | ||
spec.dday += delta; | ||
break; | ||
case TimeToken.HOURS: | ||
spec.dhour += delta; | ||
break; | ||
case TimeToken.MINUTES: | ||
spec.dmin += delta; | ||
break; | ||
case TimeToken.SECONDS: | ||
default: // default is 'seconds' | ||
spec.dsec += delta; | ||
break; | ||
} | ||
} | ||
|
||
private void timeOfDay() { | ||
int hour, minute = 0; | ||
/* save token status in case we must abort */ | ||
scanner.saveState(); | ||
/* first pick out the time of day - we assume a HH (COLON|DOT) MM time */ | ||
if (token.value.length() > 2) { | ||
//Definitely not an hour specification; probably a date or something. Give up now | ||
return; | ||
} | ||
hour = Integer.parseInt(token.value); | ||
token = scanner.nextToken(); | ||
|
||
spec.hour = hour; | ||
spec.min = minute; | ||
spec.sec = 0; | ||
if (spec.hour == 24) { | ||
spec.hour = 0; | ||
spec.day++; | ||
} | ||
} | ||
|
||
public TimeSpec parse() { | ||
long now = getTime(); | ||
return parse(now); | ||
} | ||
|
||
public TimeSpec parse(long now) { | ||
int hr = 0; | ||
spec.localtime(now); | ||
token = scanner.nextToken(); | ||
switch (token.id) { | ||
case TimeToken.PLUS: | ||
case TimeToken.MINUS: | ||
break; /* jump to OFFSET-SPEC part */ | ||
case TimeToken.START: | ||
spec.type = TimeSpec.TYPE_START; | ||
/* FALLTHRU */ | ||
case TimeToken.END: | ||
if (spec.type != TimeSpec.TYPE_START) { | ||
spec.type = TimeSpec.TYPE_END; | ||
} | ||
/* FALLTHRU */ | ||
case TimeToken.NOW: | ||
int time_reference = token.id; | ||
if (token.id != TimeToken.NOW) { | ||
spec.year = spec.month = spec.day = spec.hour = spec.min = spec.sec = 0; | ||
} | ||
token = scanner.nextToken(); | ||
if (token.id == TimeToken.PLUS || token.id == TimeToken.MINUS) { | ||
break; | ||
} | ||
if (time_reference == TimeToken.START || time_reference == TimeToken.END) { | ||
throw new RuntimeException("Words 'start' or 'end' MUST be followed by +|- offset"); | ||
} | ||
else if (token.id != TimeToken.EOF) { | ||
throw new RuntimeException("If 'now' or 'epoch' is followed by a token it must be +|- offset"); | ||
} | ||
break; | ||
case TimeToken.NUMBER: | ||
timeOfDay(); | ||
break; | ||
default: | ||
throw new RuntimeException("Unparsable time: " + token.value); | ||
} | ||
|
||
if (token.id == TimeToken.PLUS || token.id == TimeToken.MINUS) { | ||
scanner.setContext(false); | ||
while (token.id == TimeToken.PLUS || token.id == TimeToken.MINUS || | ||
token.id == TimeToken.NUMBER) { | ||
if (token.id == TimeToken.NUMBER) { | ||
plusMinus(PREVIOUS_OP); | ||
} | ||
else { | ||
plusMinus(token.id); | ||
} | ||
token = scanner.nextToken(); | ||
/* We will get EOF eventually but that's OK, since | ||
token() will return us as many EOFs as needed */ | ||
} | ||
} | ||
/* now we should be at EOF */ | ||
if (token.id != TimeToken.EOF) { | ||
throw new RuntimeException("Unparsable trailing text: " + token.value); | ||
} | ||
return spec; | ||
} | ||
|
||
public static long getTime() { | ||
return (System.currentTimeMillis() + 500L) / 1000L; | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
frostmourne-common/src/main/java/com/autohome/frostmourne/common/time/TimeParserUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.autohome.frostmourne.common.time; | ||
|
||
/** | ||
* description | ||
* | ||
* @author kechangqing | ||
* @since 2022/9/30 18:06 | ||
*/ | ||
public class TimeParserUtil { | ||
|
||
public static long parse(String str) { | ||
TimeParser timeParser = new TimeParser(str); | ||
TimeSpec timeSpec = timeParser.parse(); | ||
return timeSpec.getTimestamp(); | ||
} | ||
|
||
public static long parse(String str, long nowInSeconds) { | ||
TimeParser timeParser = new TimeParser(str); | ||
TimeSpec timeSpec = timeParser.parse(nowInSeconds); | ||
return timeSpec.getTimestamp(); | ||
} | ||
} |
126 changes: 126 additions & 0 deletions
126
frostmourne-common/src/main/java/com/autohome/frostmourne/common/time/TimeScanner.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package com.autohome.frostmourne.common.time; | ||
|
||
/** | ||
* description | ||
* | ||
* @author kechangqing | ||
* @since 2022/9/30 16:46 | ||
*/ | ||
public class TimeScanner { | ||
|
||
private String dateString; | ||
|
||
private int pos, pos_save; | ||
private TimeToken token, token_save; | ||
|
||
static final TimeToken[] WORDS = { | ||
new TimeToken("now", TimeToken.NOW), new TimeToken("n", TimeToken.NOW), new TimeToken("start", TimeToken.START), new TimeToken("s", TimeToken.START), | ||
}; | ||
|
||
static TimeToken[] MULTIPLIERS = {new TimeToken("second", TimeToken.SECONDS), | ||
new TimeToken("seconds", TimeToken.SECONDS), | ||
new TimeToken("sec", TimeToken.SECONDS), | ||
new TimeToken("s", TimeToken.SECONDS), | ||
new TimeToken("minute", TimeToken.MINUTES), | ||
new TimeToken("minutes", TimeToken.MINUTES), | ||
new TimeToken("min", TimeToken.MINUTES), | ||
new TimeToken("m", TimeToken.MINUTES), | ||
new TimeToken("hour", TimeToken.HOURS), | ||
new TimeToken("hours", TimeToken.HOURS), | ||
new TimeToken("hr", TimeToken.HOURS), | ||
new TimeToken("h", TimeToken.HOURS), | ||
new TimeToken("day", TimeToken.DAYS), | ||
new TimeToken("days", TimeToken.DAYS), | ||
new TimeToken("d", TimeToken.DAYS), | ||
new TimeToken("week", TimeToken.WEEKS), | ||
new TimeToken("weeks", TimeToken.WEEKS), | ||
new TimeToken("wk", TimeToken.WEEKS), | ||
new TimeToken("w", TimeToken.WEEKS), | ||
new TimeToken("Month", TimeToken.MONTHS), | ||
new TimeToken("Months", TimeToken.MONTHS), | ||
new TimeToken("Mon", TimeToken.MONTHS), | ||
new TimeToken("year", TimeToken.YEARS), | ||
new TimeToken("years", TimeToken.YEARS), | ||
new TimeToken("yr", TimeToken.YEARS), | ||
new TimeToken("y", TimeToken.YEARS), | ||
new TimeToken(null, 0) | ||
}; | ||
|
||
TimeToken[] specials = WORDS; | ||
|
||
public TimeScanner(String dateString) { | ||
this.dateString = dateString; | ||
} | ||
|
||
void setContext(boolean parsingWords) { | ||
specials = parsingWords ? WORDS : MULTIPLIERS; | ||
} | ||
|
||
TimeToken nextToken() { | ||
StringBuffer buffer = new StringBuffer(""); | ||
while (pos < dateString.length()) { | ||
char c = dateString.charAt(pos++); | ||
if (Character.isWhitespace(c) || c == '_' || c == ',') { | ||
continue; | ||
} | ||
buffer.append(c); | ||
if (Character.isDigit(c)) { | ||
// pick as many digits as possible | ||
while (pos < dateString.length()) { | ||
char next = dateString.charAt(pos); | ||
if (Character.isDigit(next)) { | ||
buffer.append(next); | ||
pos++; | ||
} else { | ||
break; | ||
} | ||
} | ||
String value = buffer.toString(); | ||
return token = new TimeToken(value, TimeToken.NUMBER); | ||
} | ||
if (Character.isLetter(c)) { | ||
// pick as many letters as possible | ||
while (pos < dateString.length()) { | ||
char next = dateString.charAt(pos); | ||
if (Character.isLetter(next)) { | ||
buffer.append(next); | ||
pos++; | ||
} else { | ||
break; | ||
} | ||
} | ||
String value = buffer.toString(); | ||
return token = new TimeToken(value, parseToken(value)); | ||
} | ||
switch (c) { | ||
case '+': | ||
return token = new TimeToken("+", TimeToken.PLUS); | ||
case '-': | ||
return token = new TimeToken("-", TimeToken.MINUS); | ||
default: | ||
pos--; | ||
return token = new TimeToken(null, TimeToken.EOF); | ||
} | ||
} | ||
return token = new TimeToken(null, TimeToken.EOF); | ||
} | ||
|
||
void saveState() { | ||
token_save = token; | ||
pos_save = pos; | ||
} | ||
|
||
TimeToken restoreState() { | ||
pos = pos_save; | ||
return token = token_save; | ||
} | ||
|
||
private int parseToken(String arg) { | ||
for (int i = 0; specials[i].value != null; i++) { | ||
if (specials[i].value.equalsIgnoreCase(arg)) { | ||
return specials[i].id; | ||
} | ||
} | ||
return TimeToken.ID; | ||
} | ||
} |
Oops, something went wrong.