-
Notifications
You must be signed in to change notification settings - Fork 8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
metric: Add Prometheus exporter module for Sentinel metrics (#3173)
- Loading branch information
Showing
11 changed files
with
564 additions
and
0 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
102 changes: 102 additions & 0 deletions
102
sentinel-extension/sentinel-prometheus-metric-exporter/README.md
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,102 @@ | ||
# Sentinel Prometheus Exporter | ||
|
||
Sentinel Prometheus Exporter is a module which provides the Sentinel metrics data for prometheus. | ||
|
||
You can integrate it into your Sentinel application, and then get the sentinel metrics in your prometheus. | ||
|
||
## How it works | ||
|
||
when the prometheus server collect the sentinel metrics,it get metrics from sentinel logs | ||
![image](https://github.com/alibaba/Sentinel/assets/71377602/2982209b-a3c7-403b-ae50-1dc7a17f90b7) | ||
|
||
## How to use | ||
|
||
To use Sentinel Prometheus Exporter, you should add the following dependency: | ||
|
||
### 1. add sentinel-prometheus-exporter | ||
|
||
```xml | ||
<dependency> | ||
<groupId>com.alibaba.csp</groupId> | ||
<artifactId>sentinel-prometheus-metric-exporter</artifactId> | ||
<version>x.y.z</version> | ||
</dependency> | ||
``` | ||
|
||
### 2. add prometheus dependency | ||
|
||
```xml | ||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>simpleclient</artifactId> | ||
<version>0.3.0</version> | ||
</dependency> | ||
``` | ||
|
||
```xml | ||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>simpleclient_httpserver</artifactId> | ||
<version>0.3.0</version> | ||
</dependency> | ||
``` | ||
|
||
### 3. set prometheus.yml with fetch config | ||
|
||
```yaml | ||
scrape_configs: | ||
- job_name: 'sentinelMetrics' | ||
static_configs: | ||
- targets: ['localhost:9092'] | ||
``` | ||
```yaml | ||
Note: the port needs to be the same as the value in the configuration (csp.sentinel.prometheus.fetch.port) | ||
``` | ||
## Params for exporter | ||
you can set system params to control the exporter behavior | ||
### 1.csp.sentinel.prometheus.fetch.port | ||
the port for prometheus exporter,default 9092 | ||
### 2.csp.sentinel.prometheus.fetch.size | ||
the max fetch nums for prometheus exporter,in case the memory is not enough,default 1024 | ||
### 3.csp.sentinel.prometheus.fetch.delay | ||
the delay time for fetching , may be it is still do some statistics work according to the sliding window size when fetching, | ||
so need to set the delay time to insure the accuracy. | ||
unit: second | ||
default: 0 | ||
### 4.csp.sentinel.prometheus.fetch.identify | ||
set the resource which need to fetch,default null,fetch all resources | ||
### 5.csp.sentinel.prometheus.fetch.types | ||
the types need to fetch,such as passQps,concurrency | ||
format: "xx|xx|xx" | ||
default: "passQps|blockQps|exceptionQps|rt|concurrency" | ||
you can reset the types as you need to,exm: "passQps|rt|concurrency|occupiedPassQps" | ||
the type is same as the MetricNode class variables, with range: | ||
{"passQps","blockQps","successQps","exceptionQps","rt","occupiedPassQps","concurrency"} | ||
### 6.csp.sentinel.prometheus.app | ||
set the appName when do PromSQL | ||
## how it looks | ||
![image](https://github.com/alibaba/Sentinel/assets/71377602/dedde134-53ed-4b4e-b184-98e55184aacf) |
42 changes: 42 additions & 0 deletions
42
sentinel-extension/sentinel-prometheus-metric-exporter/pom.xml
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,42 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>com.alibaba.csp</groupId> | ||
<artifactId>sentinel-parent</artifactId> | ||
<version>2.0.0-alpha</version> | ||
<relativePath>../../pom.xml</relativePath> | ||
</parent> | ||
|
||
<artifactId>sentinel-prometheus-metric-exporter</artifactId> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.alibaba.csp</groupId> | ||
<artifactId>sentinel-core</artifactId> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>simpleclient</artifactId> | ||
<version>0.3.0</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>simpleclient_httpserver</artifactId> | ||
<version>0.3.0</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
51 changes: 51 additions & 0 deletions
51
...s-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/prom/MetricConstants.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,51 @@ | ||
/* | ||
* Copyright 1999-2019 Alibaba Group Holding Ltd. | ||
* | ||
* Licensed 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 | ||
* | ||
* https://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 com.alibaba.csp.sentinel.metric.prom; | ||
|
||
/** | ||
* The{@link PromExporterInit} the Collector for prometheus exporter. | ||
* | ||
* @author karl-sy | ||
* @date 2023-08-08 09:30 | ||
* @since 2.0.0 | ||
*/ | ||
public final class MetricConstants { | ||
|
||
public static final String METRIC_HELP = "sentinel_metrics"; | ||
|
||
public static final String RESOURCE = "resource"; | ||
|
||
public static final String CLASSIFICATION = "classification"; | ||
|
||
public static final String METRIC_TYPE = "type"; | ||
|
||
public static final String PASS_QPS = "passQps"; | ||
|
||
public static final String BLOCK_QPS = "blockQps"; | ||
|
||
public static final String SUCCESS_QPS = "successQps"; | ||
|
||
public static final String EXCEPTION_QPS = "exceptionQps"; | ||
|
||
public static final String RT = "rt"; | ||
|
||
public static final String OCC_PASS_QPS = "occupiedPassQps"; | ||
|
||
public static final String CONCURRENCY = "concurrency"; | ||
|
||
private MetricConstants() { | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
...-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/prom/PromExporterInit.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,54 @@ | ||
/* | ||
* Copyright 1999-2021 Alibaba Group Holding Ltd. | ||
* | ||
* Licensed 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 com.alibaba.csp.sentinel.metric.prom; | ||
|
||
import com.alibaba.csp.sentinel.init.InitFunc; | ||
import com.alibaba.csp.sentinel.log.RecordLog; | ||
import com.alibaba.csp.sentinel.metric.prom.collector.SentinelCollector; | ||
import com.alibaba.csp.sentinel.metric.prom.config.PrometheusGlobalConfig; | ||
import io.prometheus.client.exporter.HTTPServer; | ||
|
||
/** | ||
* The{@link PromExporterInit} the InitFunc for prometheus exporter. | ||
* | ||
* @author karl-sy | ||
* @date 2023-07-13 21:15 | ||
* @since 2.0.0 | ||
*/ | ||
public class PromExporterInit implements InitFunc { | ||
|
||
@Override | ||
public void init() throws Exception { | ||
HTTPServer server = null; | ||
try { | ||
new SentinelCollector().register(); | ||
// 开启http服务供prometheus调用 | ||
// 默认只提供一个接口 http://ip:port/metrics,返回所有指标 | ||
int promPort = PrometheusGlobalConfig.getPromFetchPort(); | ||
server = new HTTPServer(promPort); | ||
} catch (Throwable e) { | ||
RecordLog.warn("[PromExporterInit] failed to init prometheus exporter with exception:", e); | ||
} | ||
|
||
HTTPServer finalServer = server; | ||
Runtime.getRuntime().addShutdownHook(new Thread(() -> { | ||
if (finalServer != null) { | ||
finalServer.stop(); | ||
} | ||
})); | ||
} | ||
|
||
} |
127 changes: 127 additions & 0 deletions
127
...orter/src/main/java/com/alibaba/csp/sentinel/metric/prom/collector/SentinelCollector.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,127 @@ | ||
/* | ||
* Copyright 1999-2021 Alibaba Group Holding Ltd. | ||
* | ||
* Licensed 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 com.alibaba.csp.sentinel.metric.prom.collector; | ||
|
||
import com.alibaba.csp.sentinel.config.SentinelConfig; | ||
import com.alibaba.csp.sentinel.log.RecordLog; | ||
import com.alibaba.csp.sentinel.metric.prom.MetricConstants; | ||
import com.alibaba.csp.sentinel.metric.prom.config.PrometheusGlobalConfig; | ||
import com.alibaba.csp.sentinel.metric.prom.types.GaugeMetricFamily; | ||
import com.alibaba.csp.sentinel.node.metric.MetricNode; | ||
import com.alibaba.csp.sentinel.node.metric.MetricSearcher; | ||
import com.alibaba.csp.sentinel.node.metric.MetricWriter; | ||
import com.alibaba.csp.sentinel.util.PidUtil; | ||
import io.prometheus.client.Collector; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
/** | ||
* The{@link PromExporterInit} Collector for prometheus exporter. | ||
* | ||
* @author karl-sy | ||
* @date 2023-07-13 21:15 | ||
* @since 2.0.0 | ||
*/ | ||
public class SentinelCollector extends Collector { | ||
|
||
private final Object lock = new Object(); | ||
|
||
private static final int ONE_SECOND = 1000; | ||
private static final String appName = PrometheusGlobalConfig.getPromFetchApp(); | ||
|
||
private static final String[] types = PrometheusGlobalConfig.getPromFetchTypes(); | ||
|
||
private static final String identify = PrometheusGlobalConfig.getPromFetchIdentify(); | ||
|
||
private static final int fetchSize = PrometheusGlobalConfig.getPromFetchSize(); | ||
|
||
private static final int delayTime = PrometheusGlobalConfig.getPromFetchDelayTime(); | ||
|
||
private volatile MetricSearcher searcher; | ||
|
||
private volatile Long lastFetchTime; | ||
|
||
@Override | ||
public List<MetricFamilySamples> collect() { | ||
if (searcher == null) { | ||
synchronized (lock) { | ||
if (searcher == null) { | ||
searcher = new MetricSearcher(MetricWriter.METRIC_BASE_DIR, | ||
MetricWriter.formMetricFileName(SentinelConfig.getAppName(), PidUtil.getPid())); | ||
} | ||
RecordLog.warn("[SentinelCollector] init sentinel metrics searcher with appName:{}", appName); | ||
lastFetchTime = System.currentTimeMillis() / ONE_SECOND * ONE_SECOND; | ||
} | ||
} | ||
|
||
List<MetricFamilySamples> list = new ArrayList<>(); | ||
|
||
long endTime = System.currentTimeMillis() / ONE_SECOND * ONE_SECOND - (long) delayTime * ONE_SECOND; | ||
try { | ||
List<MetricNode> nodes = searcher.findByTimeAndResource(lastFetchTime, endTime, identify); | ||
if(nodes == null){ | ||
return list; | ||
} | ||
if(nodes.size() > fetchSize){ | ||
nodes = nodes.subList(0,fetchSize); | ||
} | ||
GaugeMetricFamily metricFamily = new GaugeMetricFamily(appName, MetricConstants.METRIC_HELP, | ||
Arrays.asList(MetricConstants.RESOURCE, MetricConstants.CLASSIFICATION, | ||
MetricConstants.METRIC_TYPE)); | ||
for (MetricNode node : nodes) { | ||
long recordTime = node.getTimestamp(); | ||
for (String type : types) { | ||
double val = getTypeVal(node,type); | ||
metricFamily.addMetric(Arrays.asList(node.getResource(), String.valueOf(node.getClassification()),type), val,recordTime); | ||
} | ||
} | ||
list.add(metricFamily); | ||
} catch (Exception e) { | ||
RecordLog.warn("[SentinelCollector] failed to fetch sentinel metrics with exception:", e); | ||
}finally { | ||
lastFetchTime = endTime + ONE_SECOND; | ||
} | ||
|
||
return list; | ||
} | ||
|
||
public double getTypeVal(MetricNode node,String type){ | ||
if(MetricConstants.PASS_QPS.equals(type)){ | ||
return node.getPassQps(); | ||
} | ||
if(MetricConstants.BLOCK_QPS.equals(type)){ | ||
return node.getBlockQps(); | ||
} | ||
if(MetricConstants.SUCCESS_QPS.equals(type)){ | ||
return node.getSuccessQps(); | ||
} | ||
if(MetricConstants.EXCEPTION_QPS.equals(type)){ | ||
return node.getExceptionQps(); | ||
} | ||
if(MetricConstants.RT.equals(type)){ | ||
return node.getRt(); | ||
} | ||
if(MetricConstants.OCC_PASS_QPS.equals(type)){ | ||
return node.getOccupiedPassQps(); | ||
} | ||
if(MetricConstants.CONCURRENCY.equals(type)){ | ||
return node.getConcurrency(); | ||
} | ||
return -1.0; | ||
} | ||
} |
Oops, something went wrong.