javeme commented on code in PR #2286: URL: https://github.com/apache/incubator-hugegraph/pull/2286#discussion_r1324632529
########## hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/PathFilter.java: ########## @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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 org.apache.hugegraph.api.filter; + +import java.io.IOException; + +import jakarta.inject.Singleton; +import jakarta.ws.rs.container.ContainerRequestContext; +import jakarta.ws.rs.container.ContainerRequestFilter; +import jakarta.ws.rs.container.PreMatching; +import jakarta.ws.rs.ext.Provider; + +@Provider +@Singleton +@PreMatching +public class PathFilter implements ContainerRequestFilter { + + @Override + public void filter(ContainerRequestContext context) + throws IOException { + + context.setProperty("request_time", System.currentTimeMillis()); Review Comment: can we define a const var for "request_time"? ########## hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/PathFilter.java: ########## @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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 org.apache.hugegraph.api.filter; + +import java.io.IOException; + +import jakarta.inject.Singleton; +import jakarta.ws.rs.container.ContainerRequestContext; +import jakarta.ws.rs.container.ContainerRequestFilter; +import jakarta.ws.rs.container.PreMatching; +import jakarta.ws.rs.ext.Provider; + +@Provider +@Singleton +@PreMatching +public class PathFilter implements ContainerRequestFilter { + + @Override + public void filter(ContainerRequestContext context) + throws IOException { + + context.setProperty("request_time", System.currentTimeMillis()); + Review Comment: remove a blank line ########## hugegraph-api/src/main/java/org/apache/hugegraph/api/metrics/MetricsAPI.java: ########## @@ -158,4 +177,253 @@ public String timers() { ServerReporter reporter = ServerReporter.instance(); return JsonUtil.toJson(reporter.timers()); } + + + @GET + @Timed + @Produces(APPLICATION_TEXT_WITH_CHARSET) + @RolesAllowed({"admin", "$owner= $action=metrics_read"}) + public String all(@Context GraphManager manager, + @QueryParam("type") String type) { + + if (type != null && type.equals(JSON_STR)) { + return baseMetricAll(); + } else { + return baseMetricPrometheusAll(); + } + } + + @GET + @Path("statistics") + @Timed + @Produces(APPLICATION_TEXT_WITH_CHARSET) + @RolesAllowed({"admin", "$owner= $action=metrics_read"}) + public String statistics(@QueryParam("type") String type) { + Map<String, Map<String, Object>> metricMap = statistics(); + + if (type != null && type.equals(JSON_STR)) { + return JsonUtil.toJson(metricMap); + } + return statisticsProm(metricMap); + Review Comment: ditto ########## hugegraph-api/src/main/java/org/apache/hugegraph/api/metrics/MetricsAPI.java: ########## @@ -158,4 +177,253 @@ public String timers() { ServerReporter reporter = ServerReporter.instance(); return JsonUtil.toJson(reporter.timers()); } + + + @GET + @Timed + @Produces(APPLICATION_TEXT_WITH_CHARSET) + @RolesAllowed({"admin", "$owner= $action=metrics_read"}) + public String all(@Context GraphManager manager, + @QueryParam("type") String type) { + + if (type != null && type.equals(JSON_STR)) { + return baseMetricAll(); + } else { + return baseMetricPrometheusAll(); + } + } + + @GET + @Path("statistics") + @Timed + @Produces(APPLICATION_TEXT_WITH_CHARSET) + @RolesAllowed({"admin", "$owner= $action=metrics_read"}) + public String statistics(@QueryParam("type") String type) { + Map<String, Map<String, Object>> metricMap = statistics(); + + if (type != null && type.equals(JSON_STR)) { + return JsonUtil.toJson(metricMap); + } + return statisticsProm(metricMap); + + } + + + public String baseMetricAll() { + ServerReporter reporter = ServerReporter.instance(); + Map<String, Map<String, ? extends Metric>> result = new LinkedHashMap<>(); + result.put("gauges", reporter.gauges()); + result.put("counters", reporter.counters()); + result.put("histograms", reporter.histograms()); + result.put("meters", reporter.meters()); + result.put("timers", reporter.timers()); + return JsonUtil.toJson(result); + } + + private String baseMetricPrometheusAll() { + Review Comment: ditto ########## hugegraph-api/src/main/java/org/apache/hugegraph/api/metrics/MetricsAPI.java: ########## @@ -158,4 +177,253 @@ public String timers() { ServerReporter reporter = ServerReporter.instance(); return JsonUtil.toJson(reporter.timers()); } + + + @GET + @Timed + @Produces(APPLICATION_TEXT_WITH_CHARSET) + @RolesAllowed({"admin", "$owner= $action=metrics_read"}) + public String all(@Context GraphManager manager, + @QueryParam("type") String type) { + + if (type != null && type.equals(JSON_STR)) { + return baseMetricAll(); + } else { + return baseMetricPrometheusAll(); + } + } + + @GET + @Path("statistics") + @Timed + @Produces(APPLICATION_TEXT_WITH_CHARSET) + @RolesAllowed({"admin", "$owner= $action=metrics_read"}) + public String statistics(@QueryParam("type") String type) { + Map<String, Map<String, Object>> metricMap = statistics(); + + if (type != null && type.equals(JSON_STR)) { + return JsonUtil.toJson(metricMap); + } + return statisticsProm(metricMap); + + } + + Review Comment: ditto ########## hugegraph-api/src/main/java/org/apache/hugegraph/api/metrics/MetricsAPI.java: ########## @@ -158,4 +177,253 @@ public String timers() { ServerReporter reporter = ServerReporter.instance(); return JsonUtil.toJson(reporter.timers()); } + + + @GET + @Timed + @Produces(APPLICATION_TEXT_WITH_CHARSET) + @RolesAllowed({"admin", "$owner= $action=metrics_read"}) + public String all(@Context GraphManager manager, + @QueryParam("type") String type) { + + if (type != null && type.equals(JSON_STR)) { + return baseMetricAll(); + } else { + return baseMetricPrometheusAll(); + } + } + + @GET + @Path("statistics") + @Timed + @Produces(APPLICATION_TEXT_WITH_CHARSET) + @RolesAllowed({"admin", "$owner= $action=metrics_read"}) + public String statistics(@QueryParam("type") String type) { + Map<String, Map<String, Object>> metricMap = statistics(); + + if (type != null && type.equals(JSON_STR)) { + return JsonUtil.toJson(metricMap); + } + return statisticsProm(metricMap); + + } + + + public String baseMetricAll() { + ServerReporter reporter = ServerReporter.instance(); + Map<String, Map<String, ? extends Metric>> result = new LinkedHashMap<>(); + result.put("gauges", reporter.gauges()); + result.put("counters", reporter.counters()); + result.put("histograms", reporter.histograms()); + result.put("meters", reporter.meters()); + result.put("timers", reporter.timers()); + return JsonUtil.toJson(result); + } + + private String baseMetricPrometheusAll() { + + StringBuilder promMetric = new StringBuilder(); + ServerReporter reporter = ServerReporter.instance(); + String helpName = "hugegraph_info"; + //version + promMetric.append(STR_HELP) + .append(helpName).append(END_LSTR); + promMetric.append(STR_TYPE) + .append(helpName) + .append(SPACE_STR + UNTYPED + END_LSTR); + promMetric.append(helpName) + .append("{version=\"") + .append(ApiVersion.VERSION.toString()).append("\",}") + .append(SPACE_STR + "1.0" + END_LSTR); + + //gauges + for (String key : reporter.gauges().keySet()) { + final com.codahale.metrics.Gauge<?> gauge + = reporter.gauges().get(key); + if (gauge != null) { + helpName = replaceDotDashInKey(key); + promMetric.append(STR_HELP) + .append(helpName).append(END_LSTR); + promMetric.append(STR_TYPE) + .append(helpName).append(SPACE_STR + GAUGE_TYPE + END_LSTR); + promMetric.append(helpName) + .append(SPACE_STR + gauge.getValue() + END_LSTR); + } + } + + //histograms + for (String histogramkey : reporter.histograms().keySet()) { + final Histogram histogram = reporter.histograms().get(histogramkey); + if (histogram != null) { + helpName = replaceDotDashInKey(histogramkey); + promMetric.append(STR_HELP) + .append(helpName).append(END_LSTR); + promMetric.append(STR_TYPE) + .append(helpName) + .append(SPACE_STR + HISTOGRAM_TYPE + END_LSTR); + + promMetric.append(helpName) + .append(COUNT_ATTR) + .append(histogram.getCount() + END_LSTR); + promMetric.append( + exportSnapshot(helpName, histogram.getSnapshot())); + } + } + + + //meters + for (String meterkey : reporter.meters().keySet()) { + final Meter metric = reporter.meters().get(meterkey); + if (metric != null) { + helpName = replaceDotDashInKey(meterkey); + promMetric.append(STR_HELP) + .append(helpName).append(END_LSTR); + promMetric.append(STR_TYPE) + .append(helpName) + .append(SPACE_STR + HISTOGRAM_TYPE + END_LSTR); + + promMetric.append(helpName) + .append(COUNT_ATTR) + .append(metric.getCount() + END_LSTR); + promMetric.append(helpName) + .append(MEAN_RATE_ATRR) + .append(metric.getMeanRate() + END_LSTR); + promMetric.append(helpName) + .append(ONE_MIN_RATE_ATRR) + .append(metric.getOneMinuteRate() + END_LSTR); + promMetric.append(helpName) + .append(FIVE_MIN_RATE_ATRR) + .append(metric.getFiveMinuteRate() + END_LSTR); + promMetric.append(helpName) + .append(FIFT_MIN_RATE_ATRR) + .append(metric.getFifteenMinuteRate() + END_LSTR); + } + } + + //timer + for (String timerkey : reporter.timers().keySet()) { + final com.codahale.metrics.Timer timer = reporter.timers() + .get(timerkey); + if (timer != null) { + helpName = replaceDotDashInKey(timerkey); + promMetric.append(STR_HELP) + .append(helpName).append(END_LSTR); + promMetric.append(STR_TYPE) + .append(helpName) + .append(SPACE_STR + HISTOGRAM_TYPE + END_LSTR); + + promMetric.append(helpName) + .append(COUNT_ATTR) + .append(timer.getCount() + END_LSTR); + promMetric.append(helpName) + .append(ONE_MIN_RATE_ATRR) + .append(timer.getOneMinuteRate() + END_LSTR); + promMetric.append(helpName) + .append(FIVE_MIN_RATE_ATRR) + .append(timer.getFiveMinuteRate() + END_LSTR); + promMetric.append(helpName) + .append(FIFT_MIN_RATE_ATRR) + .append(timer.getFifteenMinuteRate() + END_LSTR); + promMetric.append( + exportSnapshot(helpName, timer.getSnapshot())); + } + } + + MetricsUtil.writePrometheus(promMetric, + MetricManager.INSTANCE.getRegistry()); + + return promMetric.toString(); + } + + + private Map<String, Map<String, Object>> statistics() { + Map<String, Map<String, Object>> metricsMap = new HashMap<>(); + ServerReporter reporter = ServerReporter.instance(); + for (Map.Entry<String, Histogram> entry : reporter.histograms().entrySet()) { + // entryKey = path/method/responseTimeHistogram + String entryKey = entry.getKey(); + String[] split = entryKey.split("/"); + String lastWord = split[split.length - 1]; + if (!lastWord.equals(METRICS_PATH_RESPONSE_TIME_HISTOGRAM)) { + // original metrics dont report + continue; + } + // metricsName = path/method + String metricsName = + entryKey.substring(0, entryKey.length() - lastWord.length() - 1); + + Counter totalCounter = reporter.counters().get( + joinWithSlash(metricsName, METRICS_PATH_TOTAL_COUNTER)); + Counter failedCounter = reporter.counters().get( + joinWithSlash(metricsName, METRICS_PATH_FAILED_COUNTER)); + Counter successCounter = reporter.counters().get( + joinWithSlash(metricsName, METRICS_PATH_SUCCESS_COUNTER)); + + + Histogram histogram = entry.getValue(); + Map<String, Object> entryMetricsMap = new HashMap<>(); + entryMetricsMap.put(MetricsKeys.MAX_RESPONSE_TIME.name(), + histogram.getSnapshot().getMax()); + entryMetricsMap.put(MetricsKeys.MEAN_RESPONSE_TIME.name(), + histogram.getSnapshot().getMean()); + + entryMetricsMap.put(MetricsKeys.TOTAL_REQUEST.name(), + totalCounter.getCount()); + + if (failedCounter == null) { + entryMetricsMap.put(MetricsKeys.FAILED_REQUEST.name(), 0); + } else { + entryMetricsMap.put(MetricsKeys.FAILED_REQUEST.name(), + failedCounter.getCount()); + } + + if (successCounter == null) { + entryMetricsMap.put(MetricsKeys.SUCCESS_REQUEST.name(), 0); + } else { + entryMetricsMap.put(MetricsKeys.SUCCESS_REQUEST.name(), + successCounter.getCount()); + } + + metricsMap.put(metricsName, entryMetricsMap); + + } + return metricsMap; + } + + + private String statisticsProm(Map<String, Map<String, Object>> metricMap) { + StringBuilder promMetric = new StringBuilder(); + + //version + promMetric.append(STR_HELP) + .append(PROM_HELP_NAME).append(END_LSTR); + promMetric.append(STR_TYPE) + .append(PROM_HELP_NAME) + .append(SPACE_STR + UNTYPED + END_LSTR); + promMetric.append(PROM_HELP_NAME) + .append("{version=\"") + .append(ApiVersion.VERSION.toString()).append("\",}") + .append(SPACE_STR + "1.0" + END_LSTR); + + for (String methodKey : metricMap.keySet()) { + String metricName = replaceSlashInKey(methodKey); + promMetric.append(STR_HELP) + .append(metricName).append(END_LSTR); + promMetric.append(STR_TYPE) + .append(metricName).append(SPACE_STR + GAUGE_TYPE + END_LSTR); + Map<String, Object> itemMetricMap = metricMap.get(methodKey); + for (String labelName : itemMetricMap.keySet()) { + promMetric.append(metricName).append(LEFT_NAME_STR).append(labelName) + .append(RIGHT_NAME_STR).append(itemMetricMap.get(labelName)) + .append(END_LSTR); + } + } + return promMetric.toString(); + } + + private String joinWithSlash(String path1, String path2) { + return String.join("/", path1, path2); + } + + Review Comment: ditto ########## hugegraph-test/src/main/java/org/apache/hugegraph/api/MetricsApiTest.java: ########## @@ -39,6 +43,27 @@ public void testMetricsAll() { assertJsonContains(result, "timers"); } + @Test + public void testBaseMetricsPromAll() { + Response r = client().get(path); + assertResponseStatus(200, r); + } + + @Test + public void testStatisticsMetricsAll() { + Map<String, String> params = new HashMap<>(); + params.put("type", "json"); + Response r = client().get(path); + assertResponseStatus(200, r); + } + + @Test + public void testStatisticsMetricsPromAll() { + Response r = client().get(statistics_path); + assertResponseStatus(200, r); + } + + Review Comment: ditto ########## hugegraph-api/src/main/java/org/apache/hugegraph/metrics/MetricsUtil.java: ########## @@ -40,15 +73,146 @@ public static Counter registerCounter(Class<?> clazz, String name) { return REGISTRY.counter(MetricRegistry.name(clazz, name)); } + public static Counter registerCounter(String name) { + return REGISTRY.counter(MetricRegistry.name(name)); + } + public static Histogram registerHistogram(Class<?> clazz, String name) { return REGISTRY.histogram(MetricRegistry.name(clazz, name)); } + public static Histogram registerHistogram(String name) { + return REGISTRY.histogram(name); + } + + public static Meter registerMeter(Class<?> clazz, String name) { return REGISTRY.meter(MetricRegistry.name(clazz, name)); } public static Timer registerTimer(Class<?> clazz, String name) { return REGISTRY.timer(MetricRegistry.name(clazz, name)); } + + public static String replaceDotDashInKey(String orgKey) { + return orgKey.replace(".", "_").replace("-", "_"); + } + + public static String replaceSlashInKey(String orgKey) { + return orgKey.replace("/", "_"); + } + + public static void writePrometheus(StringBuilder promeMetrics, + MetricRegistry registry) { + // gauges + registry.getGauges().forEach((key, gauge) -> { + if (gauge != null) { + String helpName = replaceDotDashInKey(key); + promeMetrics.append(STR_HELP) + .append(helpName).append(END_LSTR); + promeMetrics.append(STR_TYPE) + .append(helpName).append(SPACE_STR + GAUGE_TYPE + END_LSTR); + promeMetrics.append(helpName).append(SPACE_STR).append(gauge.getValue()) + .append(END_LSTR); + } + }); + + // histograms + registry.getHistograms().forEach((key, histogram) -> { + if (histogram != null) { + String helpName = replaceDotDashInKey(key); + promeMetrics.append(STR_HELP) + .append(helpName).append(END_LSTR); + promeMetrics.append(STR_TYPE) + .append(helpName) + .append(SPACE_STR + HISTOGRAM_TYPE + END_LSTR); + + promeMetrics.append(helpName) + .append(COUNT_ATTR).append(histogram.getCount()).append(END_LSTR); + promeMetrics.append( + exportSnapshot(helpName, histogram.getSnapshot())); + } + }); + + // meters + registry.getMeters().forEach((key, metric) -> { + if (metric != null) { + String helpName = replaceDotDashInKey(key); + promeMetrics.append(STR_HELP) + .append(helpName).append(END_LSTR); + promeMetrics.append(STR_TYPE) + .append(helpName) + .append(SPACE_STR + HISTOGRAM_TYPE + END_LSTR); + + promeMetrics.append(helpName) + .append(COUNT_ATTR).append(metric.getCount()).append(END_LSTR); + promeMetrics.append(helpName) + .append(MEAN_RATE_ATRR).append(metric.getMeanRate()).append(END_LSTR); + promeMetrics.append(helpName) + .append(ONE_MIN_RATE_ATRR).append(metric.getOneMinuteRate()) + .append(END_LSTR); + promeMetrics.append(helpName) + .append(FIVE_MIN_RATE_ATRR).append(metric.getFiveMinuteRate()) + .append(END_LSTR); + promeMetrics.append(helpName) + .append(FIFT_MIN_RATE_ATRR).append(metric.getFifteenMinuteRate()) + .append(END_LSTR); + } + }); + + // timer + registry.getTimers().forEach((key, timer) -> { + if (timer != null) { + String helpName = replaceDotDashInKey(key); + promeMetrics.append(STR_HELP) + .append(helpName).append(END_LSTR); + promeMetrics.append(STR_TYPE) + .append(helpName) + .append(SPACE_STR + HISTOGRAM_TYPE + END_LSTR); + + promeMetrics.append(helpName) + .append(COUNT_ATTR).append(timer.getCount()).append(END_LSTR); + promeMetrics.append(helpName) + .append(ONE_MIN_RATE_ATRR).append(timer.getOneMinuteRate()) + .append(END_LSTR); + promeMetrics.append(helpName) + .append(FIVE_MIN_RATE_ATRR).append(timer.getFiveMinuteRate()) + .append(END_LSTR); + promeMetrics.append(helpName) + .append(FIFT_MIN_RATE_ATRR).append(timer.getFifteenMinuteRate()) + .append(END_LSTR); + promeMetrics.append( + exportSnapshot(helpName, timer.getSnapshot())); + } + }); + } + + public static String exportSnapshot(final String helpName, final Snapshot snapshot) { + if (snapshot != null) { Review Comment: return first if if (snapshot == null) ########## hugegraph-api/src/main/java/org/apache/hugegraph/metrics/MetricsKeys.java: ########## @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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 org.apache.hugegraph.metrics; + +public enum MetricsKeys { + // 最大响应时间 Maximum response time + // 平均响应时间 Mean response time + // 请求总数 Total Requests + // 失败数 Failed Requests + // 成功数 Success Requests + + MAX_RESPONSE_TIME(1, "MAX_RESPONSE_TIME"), + + MEAN_RESPONSE_TIME(2, "MEAN_RESPONSE_TIME"), + + TOTAL_REQUEST(3, "TOTAL_REQUEST"), + + FAILED_REQUEST(4, "FAILED_REQUEST"), + + SUCCESS_REQUEST(5, "SUCCESS_REQUEST"), + ; + + private final byte code; + private final String name; + + Review Comment: ditto -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
