Skip to content

Commit

Permalink
prometheus增加/api/v1/query_range查询监控
Browse files Browse the repository at this point in the history
prometheus增加/api/v1/query_range查询监控
  • Loading branch information
kcq committed Oct 9, 2022
1 parent 0de0e5b commit 71e2bf0
Show file tree
Hide file tree
Showing 21 changed files with 667 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ yarn dev
* ~~【1.0】发布0.9-RELEASE, 开始1.0-SNAPSHOT开发 [2022-09-19]~~
* ~~【1.0】启动脚本优化,多版本jar包使用最新版本启动 [2022-09-23]~~
* ~~【1.0】数据名增加名称模糊查询 [2022-09-25]~~
* prometheus增加/api/v1/query_range查询支持
* ~~【1.0】prometheus增加/api/v1/query_range查询支持 [2022-10-08]~~
* 增加本项目内程序日志采集至MySQL并提供查询页面,方便排查问题和监控
* Elasticsearch数据名增加kibana链接配置,在数据查询页面增加kibana地址跳转链接,方便将数据查询切换至kibana
* 短信报警方式实现,默认用阿里云短信实现
Expand Down
1 change: 1 addition & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* 【1.0】发布0.9-RELEASE, 开始1.0-SNAPSHOT开发 [2022-09-19]
* 【1.0】数据名增加名称模糊查询 [2022-09-25]
* 【1.0】prometheus增加/api/v1/query_range查询支持 [2022-10-08]

### Other

Expand Down
13 changes: 13 additions & 0 deletions doc/wiki/prometheus.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

<img src="../img/prometheus/prometheus-dataname-query.png"/>

目前已经支持 `/api/v1/query``/api/v1/query_range`

### 3 报警规则

选择上面创建的的数据名,填写查询语句,如下图:
Expand All @@ -22,6 +24,17 @@
access_evaluation_duration_count{job="grafana"} == 0
```

如果endpoint为 `/api/v1/query_range` 查询语句举例如下:

```json
{
"query": "access_evaluation_duration_count",
"start": "now - 1d",
"end": "now",
"step": "1h"
}
```

填报警规则,如下图

<img src="../img/prometheus/prometheus-rule.png"/>
Expand Down
16 changes: 16 additions & 0 deletions frostmourne-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@
<artifactId>frostmourne-common</artifactId>

<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
<exclusion>
<artifactId>junit-vintage-engine</artifactId>
<groupId>org.junit.vintage</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
Expand Down
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;
}
}
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();
}
}
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;
}
}
Loading

0 comments on commit 71e2bf0

Please sign in to comment.