Skip to content

Commit 7cbc471

Browse files
authored
Merge pull request #5222 from halibobo1205/feat/metric_jsonrpc
feat(metric): add metrics for json-rpc
2 parents 2739234 + a5c1901 commit 7cbc471

6 files changed

Lines changed: 114 additions & 1 deletion

File tree

common/src/main/java/org/tron/common/prometheus/MetricKeys.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ private Gauge() {
4444
public static class Histogram {
4545
public static final String HTTP_SERVICE_LATENCY = "tron:http_service_latency_seconds";
4646
public static final String GRPC_SERVICE_LATENCY = "tron:grpc_service_latency_seconds";
47+
public static final String JSONRPC_SERVICE_LATENCY = "tron:jsonrpc_service_latency_seconds";
4748
public static final String MINER_LATENCY = "tron:miner_latency_seconds";
4849
public static final String PING_PONG_LATENCY = "tron:ping_pong_latency_seconds";
4950
public static final String VERIFY_SIGN_LATENCY = "tron:verify_sign_latency_seconds";

common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public class MetricsHistogram {
1717
"url");
1818
init(MetricKeys.Histogram.GRPC_SERVICE_LATENCY, "Grpc Service latency.",
1919
"endpoint");
20+
init(MetricKeys.Histogram.JSONRPC_SERVICE_LATENCY, "JsonRpc Service latency.",
21+
"method");
2022
init(MetricKeys.Histogram.MINER_LATENCY, "miner latency.",
2123
"miner");
2224
init(MetricKeys.Histogram.PING_PONG_LATENCY, "node ping pong latency.");

framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
package org.tron.core.services.jsonrpc;
22

33
import com.googlecode.jsonrpc4j.HttpStatusCodeProvider;
4+
import com.googlecode.jsonrpc4j.JsonRpcInterceptor;
45
import com.googlecode.jsonrpc4j.JsonRpcServer;
56
import com.googlecode.jsonrpc4j.ProxyUtil;
67
import java.io.IOException;
8+
import java.util.Collections;
79
import javax.servlet.ServletConfig;
810
import javax.servlet.ServletException;
911
import javax.servlet.http.HttpServletRequest;
1012
import javax.servlet.http.HttpServletResponse;
1113
import lombok.extern.slf4j.Slf4j;
1214
import org.springframework.beans.factory.annotation.Autowired;
1315
import org.springframework.stereotype.Component;
16+
import org.tron.common.parameter.CommonParameter;
1417
import org.tron.core.Wallet;
1518
import org.tron.core.db.Manager;
1619
import org.tron.core.services.NodeInfoService;
@@ -29,6 +32,9 @@ public class JsonRpcServlet extends RateLimiterServlet {
2932
@Autowired
3033
private Manager manager;
3134

35+
@Autowired
36+
private JsonRpcInterceptor interceptor;
37+
3238
@Override
3339
public void init(ServletConfig config) throws ServletException {
3440
super.init(config);
@@ -57,6 +63,9 @@ public Integer getJsonRpcCode(int httpStatusCode) {
5763
rpcServer.setHttpStatusCodeProvider(httpStatusCodeProvider);
5864

5965
rpcServer.setShouldLogInvocationErrors(false);
66+
if (CommonParameter.getInstance().isMetricsPrometheusEnable()) {
67+
rpcServer.setInterceptorList(Collections.singletonList(interceptor));
68+
}
6069
}
6170

6271
@Override
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.tron.core.services.jsonrpc.interceptor;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.googlecode.jsonrpc4j.JsonRpcInterceptor;
5+
import com.googlecode.jsonrpc4j.ProxyUtil;
6+
import io.prometheus.client.Histogram;
7+
import java.lang.reflect.Method;
8+
import java.util.List;
9+
import org.springframework.stereotype.Component;
10+
import org.tron.common.prometheus.MetricKeys;
11+
import org.tron.common.prometheus.Metrics;
12+
13+
@Component
14+
public class MetricInterceptor implements JsonRpcInterceptor {
15+
16+
private final ThreadLocal<Histogram.Timer> timer = new ThreadLocal<>();
17+
18+
@Override
19+
public void preHandleJson(JsonNode json) {
20+
21+
}
22+
23+
@Override
24+
public void preHandle(Object target, Method method, List<JsonNode> params) {
25+
timer.set(Metrics.histogramStartTimer(MetricKeys.Histogram.JSONRPC_SERVICE_LATENCY,
26+
ProxyUtil.getMethodName(method)));
27+
}
28+
29+
@Override
30+
public void postHandle(Object target, Method method, List<JsonNode> params, JsonNode result) {
31+
try {
32+
Metrics.histogramObserve(timer.get());
33+
} finally {
34+
timer.remove();
35+
}
36+
}
37+
38+
@Override
39+
public void postHandleJson(JsonNode json) {
40+
41+
}
42+
}

framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ public class BlockResult {
8484
@Setter
8585
private String mixHash = ByteArray.toJsonHex(new byte[32]);
8686

87+
public BlockResult() {
88+
89+
}
90+
8791
public BlockResult(Block block, boolean fullTx, Wallet wallet) {
8892
BlockCapsule blockCapsule = new BlockCapsule(block);
8993

framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
11
package org.tron.core.jsonrpc;
22

3+
import com.alibaba.fastjson.JSON;
4+
import com.google.gson.JsonArray;
5+
import com.google.gson.JsonObject;
36
import com.google.protobuf.ByteString;
7+
import io.prometheus.client.CollectorRegistry;
48
import javax.annotation.Resource;
59
import lombok.extern.slf4j.Slf4j;
10+
import org.apache.http.client.methods.CloseableHttpResponse;
11+
import org.apache.http.client.methods.HttpPost;
12+
import org.apache.http.entity.StringEntity;
13+
import org.apache.http.impl.client.CloseableHttpClient;
14+
import org.apache.http.impl.client.HttpClients;
15+
import org.apache.http.util.EntityUtils;
616
import org.bouncycastle.util.encoders.Hex;
717
import org.junit.Assert;
818
import org.junit.Before;
919
import org.junit.Test;
1020
import org.tron.common.BaseTest;
21+
import org.tron.common.parameter.CommonParameter;
22+
import org.tron.common.prometheus.Metrics;
1123
import org.tron.common.utils.ByteArray;
1224
import org.tron.common.utils.Sha256Hash;
1325
import org.tron.core.Constant;
@@ -17,6 +29,7 @@
1729
import org.tron.core.capsule.TransactionCapsule;
1830
import org.tron.core.config.args.Args;
1931
import org.tron.core.services.NodeInfoService;
32+
import org.tron.core.services.jsonrpc.FullNodeJsonRpcHttpService;
2033
import org.tron.core.services.jsonrpc.TronJsonRpcImpl;
2134
import org.tron.core.services.jsonrpc.types.BlockResult;
2235
import org.tron.core.services.jsonrpc.types.TransactionResult;
@@ -39,9 +52,15 @@ public class JsonrpcServiceTest extends BaseTest {
3952
@Resource
4053
private Wallet wallet;
4154

55+
@Resource
56+
private FullNodeJsonRpcHttpService fullNodeJsonRpcHttpService;
57+
4258
static {
4359
dbPath = "output_jsonrpc_service_test";
4460
Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF);
61+
CommonParameter.getInstance().setJsonRpcHttpFullNodeEnable(true);
62+
CommonParameter.getInstance().setMetricsPrometheusEnable(true);
63+
Metrics.init();
4564

4665
OWNER_ADDRESS =
4766
Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc";
@@ -235,4 +254,40 @@ public void testGetTransactionByHash() {
235254
transactionResult.getBlockNumber());
236255
}
237256

238-
}
257+
@Test
258+
public void testGetBlockByNumber2() {
259+
fullNodeJsonRpcHttpService.start();
260+
JsonArray params = new JsonArray();
261+
params.add(ByteArray.toJsonHex(blockCapsule.getNum()));
262+
params.add(false);
263+
JsonObject requestBody = new JsonObject();
264+
requestBody.addProperty("jsonrpc", "2.0");
265+
requestBody.addProperty("method", "eth_getBlockByNumber");
266+
requestBody.add("params", params);
267+
requestBody.addProperty("id", 1);
268+
CloseableHttpResponse response;
269+
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
270+
HttpPost httpPost = new HttpPost("http://127.0.0.1:8545/jsonrpc");
271+
httpPost.addHeader("Content-Type", "application/json");
272+
httpPost.setEntity(new StringEntity(requestBody.toString()));
273+
response = httpClient.execute(httpPost);
274+
String resp = EntityUtils.toString(response.getEntity());
275+
BlockResult blockResult = JSON.parseObject(resp).getObject("result", BlockResult.class);
276+
Assert.assertEquals(ByteArray.toJsonHex(blockCapsule.getNum()),
277+
blockResult.getNumber());
278+
Assert.assertEquals(blockCapsule.getTransactions().size(),
279+
blockResult.getTransactions().length);
280+
Assert.assertEquals("0x0000000000000000",
281+
blockResult.getNonce());
282+
response.close();
283+
Assert.assertEquals(1, CollectorRegistry.defaultRegistry.getSampleValue(
284+
"tron:jsonrpc_service_latency_seconds_count",
285+
new String[] {"method"}, new String[] {"eth_getBlockByNumber"}).intValue());
286+
} catch (Exception e) {
287+
Assert.fail(e.getMessage());
288+
} finally {
289+
fullNodeJsonRpcHttpService.stop();
290+
}
291+
}
292+
293+
}

0 commit comments

Comments
 (0)