You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2024/06/18 08:58:10 UTC
(skywalking) branch master updated: Support trace MQE query for debugging. (#12342)
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git
The following commit(s) were added to refs/heads/master by this push:
new 0b7272d813 Support trace MQE query for debugging. (#12342)
0b7272d813 is described below
commit 0b7272d813885ac6952211c80620f80bd33b47f2
Author: Wan Kai <wa...@foxmail.com>
AuthorDate: Tue Jun 18 16:58:03 2024 +0800
Support trace MQE query for debugging. (#12342)
---
docs/en/api/query-protocol.md | 6 +-
docs/en/changes/changes.md | 1 +
docs/en/debugging/query-tracing.md | 343 +++++++++++++++
docs/menu.yml | 2 +
.../apache/skywalking/mqe/rt/MQEVisitorBase.java | 469 ++++++++++++---------
.../skywalking/mqe/rt/type/ExpressionResult.java | 2 +
.../oap/server/core/alarm/provider/AlarmRule.java | 40 +-
.../server/core/alarm/provider/RunningRule.java | 82 ++--
.../server/core/query/AggregationQueryService.java | 22 +-
.../oap/server/core/query/MetricsQueryService.java | 54 ++-
.../oap/server/core/query/RecordQueryService.java | 22 +-
.../oap/server/core/query/input/Duration.java | 2 +
.../oap/server/core/query/input/Entity.java | 2 +
.../server/core/query/input/MetricsCondition.java | 2 +
.../server/core/query/input/RecordCondition.java | 2 +
.../oap/server/core/query/input/TopNCondition.java | 2 +
.../oap/server/core/query/type/KeyValue.java | 2 +
.../DebuggingSpan.java} | 38 +-
.../core/query/type/debugging/DebuggingTrace.java | 50 +++
.../type/debugging/DebuggingTraceContext.java | 68 +++
.../debugging-query-plugin/pom.xml | 7 +-
.../oap/query/debug/DebuggingHTTPHandler.java | 89 ++++
.../oap/query/debug/DebuggingSpanRsp.java} | 33 +-
.../oap/query/debug/DebuggingTraceRsp.java} | 28 +-
.../oap/query/debug/mqe/DebuggingMQERsp.java} | 30 +-
.../oap/query/graphql/mqe/rt/MQEVisitor.java | 133 +++---
.../graphql/resolver/MetricsExpressionQuery.java | 74 ++--
.../src/main/resources/query-protocol | 2 +-
.../banyandb/BanyanDBAggregationQueryDAO.java | 124 +++++-
.../plugin/banyandb/BanyanDBRecordsQueryDAO.java | 66 ++-
.../storage/plugin/banyandb/MetadataRegistry.java | 3 +
.../banyandb/measure/BanyanDBMetricsQueryDAO.java | 86 +++-
.../elasticsearch/query/AggregationQueryEsDAO.java | 50 ++-
.../elasticsearch/query/MetricsQueryEsDAO.java | 74 +++-
.../elasticsearch/query/RecordsQueryEsDAO.java | 47 ++-
35 files changed, 1617 insertions(+), 440 deletions(-)
diff --git a/docs/en/api/query-protocol.md b/docs/en/api/query-protocol.md
index af84589b5e..40622b967b 100644
--- a/docs/en/api/query-protocol.md
+++ b/docs/en/api/query-protocol.md
@@ -90,9 +90,12 @@ extend type Query {
# Get the list of all available metrics in the current OAP server.
# Param, regex, could be used to filter the metrics by name.
listMetrics(regex: String): [MetricDefinition!]!
- execExpression(expression: String!, entity: Entity!, duration: Duration!): ExpressionResult!
+ # Param, if debug is true will enable the query tracing and return DebuggingTrace in the ExpressionResult.
+ # Param, if dumpDBRsp is true the database response will dump into the DebuggingTrace span message.
+ execExpression(expression: String!, entity: Entity!, duration: Duration!, debug: Boolean, dumpDBRsp: Boolean): ExpressionResult!
}
```
+About the query tracing, see [MQE Query Tracing](../debugging/query-tracing.md#debugging-with-graphql-bundled).
```graphql
type ExpressionResult {
@@ -103,6 +106,7 @@ type ExpressionResult {
# When type == ExpressionResultType.UNKNOWN,
# the error message includes the expression resolving errors.
error: String
+ debuggingTrace: DebuggingTrace
}
```
diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index bae2243468..6f97d08e17 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -11,6 +11,7 @@
* Remove unnecessary BanyanDB flushing logs(info).
* Increase `SW_CORE_GRPC_MAX_MESSAGE_SIZE` to 50MB.
* Support to query relation metrics through PromQL.
+* Support trace MQE query for debugging.
#### UI
diff --git a/docs/en/debugging/query-tracing.md b/docs/en/debugging/query-tracing.md
new file mode 100644
index 0000000000..3252456d83
--- /dev/null
+++ b/docs/en/debugging/query-tracing.md
@@ -0,0 +1,343 @@
+# Tracing MQE Execution
+SkyWalking OAP provides the metrics query tracing to help users debug and diagnose the query performance for the SkyWalking backend self.
+
+## Tracing Structure
+- Trace
+
+| Field | Description |
+|-----------|-------------------------------------------------|
+| traceId | The unique ID of the trace |
+| condition | The query conditions |
+| startTime | The start time of the trace. In nanoseconds |
+| endTime | The end time of the trace. In nanoseconds |
+| duration | The operation name of the trace. in nanoseconds |
+| spans | spans in this trace |
+
+- Span
+
+| Field | Description |
+|--------------|------------------------------------------------------------------------------------------------------------------|
+| spanId | The unique ID of the span |
+| parentSpanId | The parent span ID of the span |
+| operation | The operation name of the span |
+| startTime | The start time of the span. In nanoseconds |
+| endTime | The end time of the span. In nanoseconds |
+| duration | The duration of the span. In nanoseconds |
+| msg | The message of the span, could include additional info such as request condition and response from the Database |
+| error | The error message of the span, if the span has an error. |
+
+
+## MQE Query Tracing
+MQE query tracing used to trace the query performance of the MQE query.
+
+### Debugging through HTTP APIs
+The MQE query tracing service is provided within the OAP rest server,
+which could be accessed through HTTP GET `http://{core restHost}:{core restPort}/debugging/query/mqe?{parameters}`.
+
+- Parameters
+
+| Field | Description | Required |
+|---------------------|-----------------------------------------------------------------------------|----------------------------|
+| dumpDBRsp | Dump the response from the database, **support Elasticsearch and BanyanDB** | No, default value is false |
+| expression | The MQE query expression | Yes |
+| startTime | The start time of the query | Yes |
+| endTime | The end time of the query | Yes |
+| step | The query step | Yes |
+| service | The service name | Yes |
+| serviceLayer | The service layer name | Yes |
+| serviceInstance | The service instance name | No |
+| endpoint | The endpoint name | No |
+| process | The process name | No |
+| destService | The destination service name | No |
+| destServiceInstance | The destination service instance name | No |
+| destServiceInstance | The destination service instance name | No |
+| destEndpoint | The destination endpoint name | No |
+| destProcess | The destination process name | No |
+
+
+The time and step parameters are follow the [Duration](../api/query-protocol.md#duration) format.
+
+- Example
+
+Tracing an avg query with the MQE query expression `avg(service_sla)` from 2024-06-18 11 to 2024-06-18 12 with the step HOUR for the service `mock_a_service` and the service layer `GENERAL`.
+
+```shell
+curl -X GET 'http://127.0.0.1:12800/debugging/query/mqe?dumpDBRsp=true&expression=avg(service_sla)&startTime=2024-06-18%2011&endTime=2024-06-18%2012&step=HOUR&service=mock_a_service&serviceLayer=GENERAL'
+```
+
+Response will include query result and the execTrace information:
+
+```yaml
+type: "SINGLE_VALUE"
+results:
+ - metric:
+ labels: []
+ values:
+ - id: null
+ value: "10000"
+ traceID: null
+ doubleValue: 10000.0
+ emptyValue: false
+error: null
+execTrace:
+ traceId: "a50910fe-c966-4249-87f9-e471e55cf92f"
+ condition: "Expression: avg(service_sla), Entity: Entity(scope=null, serviceName=mock_a_service,\
+ \ normal=true, serviceInstanceName=null, endpointName=null, processName=null,\
+ \ destServiceName=null, destNormal=null, destServiceInstanceName=null, destEndpointName=null,\
+ \ destProcessName=null), Duration: Duration(start=2024-06-18 11, end=2024-06-18\
+ \ 12, step=HOUR)"
+ startTime: 61636369350002
+ endTime: 61636374541189
+ duration: 5191187
+ rootSpan:
+ spanId: 0
+ parentSpanId: -1
+ operation: "MQE query"
+ startTime: 61636369352761
+ endTime: 61636374539893
+ duration: 5187132
+ msg: null
+ error: null
+ childSpans:
+ - spanId: 1
+ parentSpanId: 0
+ operation: "MQE syntax analysis"
+ startTime: 61636369357437
+ endTime: 61636369443631
+ duration: 86194
+ msg: null
+ error: null
+ childSpans: []
+ - spanId: 2
+ parentSpanId: 0
+ operation: "MQE Aggregation OP: avg(service_sla)"
+ startTime: 61636369458018
+ endTime: 61636374440560
+ duration: 4982542
+ msg: null
+ error: null
+ childSpans:
+ - spanId: 3
+ parentSpanId: 2
+ operation: "MQE Metric OP: service_sla"
+ startTime: 61636369468839
+ endTime: 61636374373771
+ duration: 4904932
+ msg: null
+ error: null
+ childSpans:
+ - spanId: 4
+ parentSpanId: 3
+ operation: "Query Service"
+ startTime: 61636369481077
+ endTime: 61636374187132
+ duration: 4706055
+ msg: "readMetricsValues, MetricsCondition: MetricsCondition(name=service_sla,\
+ \ entity=Entity(scope=null, serviceName=mock_a_service, normal=true, serviceInstanceName=null,\
+ \ endpointName=null, processName=null, destServiceName=null, destNormal=null,\
+ \ destServiceInstanceName=null, destEndpointName=null, destProcessName=null)),\
+ \ Duration: Duration(start=2024-06-18 11, end=2024-06-18 12, step=HOUR)"
+ error: null
+ childSpans:
+ - spanId: 5
+ parentSpanId: 4
+ operation: "Query Dao: readMetricsValues"
+ startTime: 61636369516511
+ endTime: 61636374186023
+ duration: 4669512
+ msg: "MetricsCondition: MetricsCondition(name=service_sla, entity=Entity(scope=Service,\
+ \ serviceName=mock_a_service, normal=true, serviceInstanceName=null,\
+ \ endpointName=null, processName=null, destServiceName=null, destNormal=null,\
+ \ destServiceInstanceName=null, destEndpointName=null, destProcessName=null)),\
+ \ ValueColumnName: percentage, Duration: Duration(start=2024-06-18 11,\
+ \ end=2024-06-18 12, step=HOUR)"
+ error: null
+ childSpans:
+ - spanId: 6
+ parentSpanId: 5
+ operation: "Query Elasticsearch"
+ startTime: 61636369738832
+ endTime: 61636374107033
+ duration: 4368201
+ msg: "Condition: indices: [metrics-all-20240618]\n Response: {\"docs\"\
+ :[{\"found\":true,\"id\":\"service_sla_2024061811_bW9ja19hX3NlcnZpY2U\\\
+ u003d.1\",\"source\":{\"metric_table\":\"service_sla\",\"total\":130,\"\
+ percentage\":10000,\"match\":130,\"time_bucket\":2024061811,\"entity_id\"\
+ :\"bW9ja19hX3NlcnZpY2U\\u003d.1\"}},{\"found\":false,\"id\":\"service_sla_2024061812_bW9ja19hX3NlcnZpY2U\\\
+ u003d.1\"}]}"
+ error: null
+ childSpans: []
+```
+
+### Debugging with GraphQL bundled
+When querying the metrics though the [Metrics V3 APIs](../api/query-protocol.md#v3-apis),
+the MQE query tracing service is also provided within the GraphQL bundled.
+
+```graphql
+extend type Query {
+ ...
+ # Param, if debug is true will enable the query tracing and return DebuggingTrace in the ExpressionResult.
+ # Param, if dumpDBRsp is true the database response will dump into the DebuggingTrace span message.
+ execExpression(expression: String!, entity: Entity!, duration: Duration!, debug: Boolean, dumpDBRsp: Boolean): ExpressionResult!
+}
+```
+
+```graphql
+type ExpressionResult {
+ ...
+ debuggingTrace: DebuggingTrace
+}
+```
+
+- Example
+
+Query the metrics using the above condition through the GraphQL and tracing the query:
+```text
+http://127.0.0.1:12800/graphql
+```
+
+```graphql
+{
+ execExpression(expression: "avg(service_sla)", entity: {serviceName: "mock_a_service", normal: true}, duration: {start: "2024-06-18 11", end: "2024-06-18 12", step: HOUR}, debug: true, dumpDBRsp: true) {
+ type
+ error
+ results {
+ metric {
+ labels {
+ key
+ value
+ }
+ }
+ values {
+ id
+ value
+ traceID
+ }
+ }
+ debuggingTrace {
+ traceId
+ condition
+ startTime
+ endTime
+ duration
+ spans {
+ spanId
+ parentSpanId
+ operation
+ startTime
+ endTime
+ duration
+ msg
+ error
+ }
+ }
+ }
+}
+
+
+```
+Response will include query result and the execTrace information:
+
+```json
+{
+ "data": {
+ "execExpression": {
+ "type": "SINGLE_VALUE",
+ "error": null,
+ "results": [
+ {
+ "metric": {
+ "labels": []
+ },
+ "values": [
+ {
+ "id": null,
+ "value": "10000",
+ "traceID": null
+ }
+ ]
+ }
+ ],
+ "debuggingTrace": {
+ "traceId": "7caa6529-9a72-4878-ab82-7a9ca032a97b",
+ "condition": "Expression: avg(service_sla), Entity: Entity(scope=null, serviceName=mock_a_service, normal=true, serviceInstanceName=null, endpointName=null, processName=null, destServiceName=null, destNormal=null, destServiceInstanceName=null, destEndpointName=null, destProcessName=null), Duration: Duration(start=2024-06-18 11, end=2024-06-18 12, step=HOUR)",
+ "startTime": 73040673584523,
+ "endTime": 73040678525541,
+ "duration": 4941018,
+ "spans": [
+ {
+ "spanId": 0,
+ "parentSpanId": -1,
+ "operation": "MQE query",
+ "startTime": 73040673586770,
+ "endTime": 73040678523624,
+ "duration": 4936854,
+ "msg": null,
+ "error": null
+ },
+ {
+ "spanId": 1,
+ "parentSpanId": 0,
+ "operation": "MQE syntax analysis",
+ "startTime": 73040673591566,
+ "endTime": 73040673677579,
+ "duration": 86013,
+ "msg": null,
+ "error": null
+ },
+ {
+ "spanId": 2,
+ "parentSpanId": 0,
+ "operation": "MQE Aggregation OP: avg(service_sla)",
+ "startTime": 73040673691700,
+ "endTime": 73040678270159,
+ "duration": 4578459,
+ "msg": null,
+ "error": null
+ },
+ {
+ "spanId": 3,
+ "parentSpanId": 2,
+ "operation": "MQE Metric OP: service_sla",
+ "startTime": 73040673704725,
+ "endTime": 73040678230548,
+ "duration": 4525823,
+ "msg": null,
+ "error": null
+ },
+ {
+ "spanId": 4,
+ "parentSpanId": 3,
+ "operation": "Query Service",
+ "startTime": 73040673717502,
+ "endTime": 73040678040891,
+ "duration": 4323389,
+ "msg": "readMetricsValues, MetricsCondition: MetricsCondition(name=service_sla, entity=Entity(scope=null, serviceName=mock_a_service, normal=true, serviceInstanceName=null, endpointName=null, processName=null, destServiceName=null, destNormal=null, destServiceInstanceName=null, destEndpointName=null, destProcessName=null)), Duration: Duration(start=2024-06-18 11, end=2024-06-18 12, step=HOUR)",
+ "error": null
+ },
+ {
+ "spanId": 5,
+ "parentSpanId": 4,
+ "operation": "Query Dao: readMetricsValues",
+ "startTime": 73040673744571,
+ "endTime": 73040678039850,
+ "duration": 4295279,
+ "msg": "MetricsCondition: MetricsCondition(name=service_sla, entity=Entity(scope=Service, serviceName=mock_a_service, normal=true, serviceInstanceName=null, endpointName=null, processName=null, destServiceName=null, destNormal=null, destServiceInstanceName=null, destEndpointName=null, destProcessName=null)), ValueColumnName: percentage, Duration: Duration(start=2024-06-18 11, end=2024-06-18 12, step=HOUR)",
+ "error": null
+ },
+ {
+ "spanId": 6,
+ "parentSpanId": 5,
+ "operation": "Query Elasticsearch",
+ "startTime": 73040673916132,
+ "endTime": 73040677997181,
+ "duration": 4081049,
+ "msg": "Condition: indices: [metrics-all-20240618]\n Response: {\"docs\":[{\"found\":true,\"id\":\"service_sla_2024061811_bW9ja19hX3NlcnZpY2U\\u003d.1\",\"source\":{\"metric_table\":\"service_sla\",\"total\":130,\"percentage\":10000,\"match\":130,\"time_bucket\":2024061811,\"entity_id\":\"bW9ja19hX3NlcnZpY2U\\u003d.1\"}},{\"found\":false,\"id\":\"service_sla_2024061812_bW9ja19hX3NlcnZpY2U\\u003d.1\"}]}",
+ "error": null
+ }
+ ]
+ }
+ }
+ }
+}
+```
diff --git a/docs/menu.yml b/docs/menu.yml
index 18fd50acbb..183edeeea3 100644
--- a/docs/menu.yml
+++ b/docs/menu.yml
@@ -340,6 +340,8 @@ catalog:
catalog:
- name: "Scratch The OAP Config Dump"
path: "/en/debugging/config_dump"
+ - name: "Tracing Query Execution"
+ path: "/en/debugging/query-tracing.md"
- name: "Academy"
catalog:
- name: "Scaling SkyWalking server automatically in kubernetes"
diff --git a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java
index 4416176b83..ec1b6cfb60 100644
--- a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java
+++ b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java
@@ -43,8 +43,12 @@ import org.apache.skywalking.mqe.rt.type.MQEValues;
import org.apache.skywalking.oap.server.core.Const;
import org.apache.skywalking.oap.server.core.query.enumeration.Step;
import org.apache.skywalking.oap.server.core.query.type.KeyValue;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.library.util.StringUtil;
+import static org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace.TRACE_CONTEXT;
+
@Slf4j
public abstract class MQEVisitorBase extends MQEParserBaseVisitor<ExpressionResult> {
public final Step queryStep;
@@ -60,293 +64,343 @@ public abstract class MQEVisitorBase extends MQEParserBaseVisitor<ExpressionResu
@Override
public ExpressionResult visitAddSubOp(MQEParser.AddSubOpContext ctx) {
- ExpressionResult left = visit(ctx.expression(0));
- if (StringUtil.isNotBlank(left.getError())) {
- return left;
- }
- ExpressionResult right = visit(ctx.expression(1));
- if (StringUtil.isNotBlank(right.getError())) {
- return right;
- }
- int opType = ctx.addSub().getStart().getType();
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Binary OP: " + ctx.getText());
try {
- return BinaryOp.doBinaryOp(left, right, opType);
- } catch (IllegalExpressionException e) {
- ExpressionResult result = new ExpressionResult();
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError(e.getMessage());
- return result;
+ ExpressionResult left = visit(ctx.expression(0));
+ if (StringUtil.isNotBlank(left.getError())) {
+ return left;
+ }
+ ExpressionResult right = visit(ctx.expression(1));
+ if (StringUtil.isNotBlank(right.getError())) {
+ return right;
+ }
+ int opType = ctx.addSub().getStart().getType();
+ try {
+ return BinaryOp.doBinaryOp(left, right, opType);
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ }
+ } finally {
+ traceContext.stopSpan(span);
}
}
@Override
public ExpressionResult visitMulDivModOp(MQEParser.MulDivModOpContext ctx) {
- ExpressionResult left = visit(ctx.expression(0));
- if (StringUtil.isNotBlank(left.getError())) {
- return left;
- }
- ExpressionResult right = visit(ctx.expression(1));
- if (StringUtil.isNotBlank(right.getError())) {
- return right;
- }
- int opType = ctx.mulDivMod().getStart().getType();
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Binary OP: " + ctx.getText());
try {
- return BinaryOp.doBinaryOp(left, right, opType);
- } catch (IllegalExpressionException e) {
- ExpressionResult result = new ExpressionResult();
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError(e.getMessage());
- return result;
+ ExpressionResult left = visit(ctx.expression(0));
+ if (StringUtil.isNotBlank(left.getError())) {
+ return left;
+ }
+ ExpressionResult right = visit(ctx.expression(1));
+ if (StringUtil.isNotBlank(right.getError())) {
+ return right;
+ }
+ int opType = ctx.mulDivMod().getStart().getType();
+ try {
+ return BinaryOp.doBinaryOp(left, right, opType);
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ }
+ } finally {
+ traceContext.stopSpan(span);
}
}
@Override
public ExpressionResult visitScalar(MQEParser.ScalarContext ctx) {
- ExpressionResult result = new ExpressionResult();
- double value = Double.parseDouble(ctx.getText());
- MQEValue mqeValue = new MQEValue();
- mqeValue.setDoubleValue(value);
- mqeValue.setEmptyValue(false);
- MQEValues mqeValues = new MQEValues();
- mqeValues.getValues().add(mqeValue);
- result.getResults().add(mqeValues);
- result.setType(ExpressionResultType.SINGLE_VALUE);
- return result;
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Scalar: " + ctx.getText());
+ try {
+ ExpressionResult result = new ExpressionResult();
+ double value = Double.parseDouble(ctx.getText());
+ MQEValue mqeValue = new MQEValue();
+ mqeValue.setDoubleValue(value);
+ mqeValue.setEmptyValue(false);
+ MQEValues mqeValues = new MQEValues();
+ mqeValues.getValues().add(mqeValue);
+ result.getResults().add(mqeValues);
+ result.setType(ExpressionResultType.SINGLE_VALUE);
+ return result;
+ } finally {
+ traceContext.stopSpan(span);
+ }
}
@Override
public ExpressionResult visitAggregationOp(MQEParser.AggregationOpContext ctx) {
- int opType = ctx.aggregation().getStart().getType();
- ExpressionResult expResult = visit(ctx.expression());
- if (StringUtil.isNotEmpty(expResult.getError())) {
- return expResult;
- }
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Aggregation OP: " + ctx.getText());
try {
- return AggregationOp.doAggregationOp(expResult, opType);
- } catch (IllegalExpressionException e) {
- ExpressionResult result = new ExpressionResult();
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError(e.getMessage());
- return result;
+ int opType = ctx.aggregation().getStart().getType();
+ ExpressionResult expResult = visit(ctx.expression());
+ if (StringUtil.isNotEmpty(expResult.getError())) {
+ return expResult;
+ }
+ try {
+ return AggregationOp.doAggregationOp(expResult, opType);
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ }
+ } finally {
+ traceContext.stopSpan(span);
}
}
@Override
public ExpressionResult visitAggregateLabelsOp(final MQEParser.AggregateLabelsOpContext ctx) {
- int funcType = ctx.aggregateLabelsFunc().getStart().getType();
- ExpressionResult expResult = visit(ctx.expression());
- if (StringUtil.isNotEmpty(expResult.getError())) {
- return expResult;
- }
-
- if (!expResult.isLabeledResult()) {
- expResult.setError("The result of expression [" + ctx.expression().getText() + "] is not a labeled result.");
- return expResult;
- }
-
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Aggregate Labels OP: " + ctx.getText());
try {
- if (expResult.getResults().isEmpty()) {
+ int funcType = ctx.aggregateLabelsFunc().getStart().getType();
+ ExpressionResult expResult = visit(ctx.expression());
+ if (StringUtil.isNotEmpty(expResult.getError())) {
return expResult;
}
- List<String> labelNames = new ArrayList<>();
- MQEParser.LabelNameListContext labelNameListContext = ctx.aggregateLabelsFunc().labelNameList();
- if (null != labelNameListContext) {
- for (MQEParser.LabelNameContext labelNameContext : labelNameListContext.labelName()) {
- // ignore the label name that does not exist in the result
- if (expResult.getResults()
- .get(0)
- .getMetric()
- .getLabels()
- .stream()
- .anyMatch(label -> label.getKey().equals(labelNameContext.getText()))) {
- labelNames.add(labelNameContext.getText());
+
+ if (!expResult.isLabeledResult()) {
+ expResult.setError(
+ "The result of expression [" + ctx.expression().getText() + "] is not a labeled result.");
+ return expResult;
+ }
+
+ try {
+ if (expResult.getResults().isEmpty()) {
+ return expResult;
+ }
+ List<String> labelNames = new ArrayList<>();
+ MQEParser.LabelNameListContext labelNameListContext = ctx.aggregateLabelsFunc().labelNameList();
+ if (null != labelNameListContext) {
+ for (MQEParser.LabelNameContext labelNameContext : labelNameListContext.labelName()) {
+ // ignore the label name that does not exist in the result
+ if (expResult.getResults()
+ .get(0)
+ .getMetric()
+ .getLabels()
+ .stream()
+ .anyMatch(label -> label.getKey().equals(labelNameContext.getText()))) {
+ labelNames.add(labelNameContext.getText());
+ }
}
}
+ return AggregateLabelsOp.doAggregateLabelsOp(expResult, funcType, labelNames);
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
}
- return AggregateLabelsOp.doAggregateLabelsOp(expResult, funcType, labelNames);
- } catch (IllegalExpressionException e) {
- ExpressionResult result = new ExpressionResult();
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError(e.getMessage());
- return result;
+ } finally {
+ traceContext.stopSpan(span);
}
}
@Override
public ExpressionResult visitMathematicalOperator0OP(MQEParser.MathematicalOperator0OPContext ctx) {
- int opType = ctx.mathematical_operator0().getStart().getType();
- ExpressionResult expResult = visit(ctx.expression());
- if (StringUtil.isNotEmpty(expResult.getError())) {
- return expResult;
- }
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Mathematical OP: " + ctx.getText());
try {
- return MathematicalFunctionOp.doFunction0Op(expResult, opType);
- } catch (IllegalExpressionException e) {
- ExpressionResult result = new ExpressionResult();
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError(e.getMessage());
- return result;
+ int opType = ctx.mathematical_operator0().getStart().getType();
+ ExpressionResult expResult = visit(ctx.expression());
+ if (StringUtil.isNotEmpty(expResult.getError())) {
+ return expResult;
+ }
+ try {
+ return MathematicalFunctionOp.doFunction0Op(expResult, opType);
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ }
+ } finally {
+ traceContext.stopSpan(span);
}
}
@Override
public ExpressionResult visitMathematicalOperator1OP(MQEParser.MathematicalOperator1OPContext ctx) {
- int opType = ctx.mathematical_operator1().getStart().getType();
- ExpressionResult expResult = visit(ctx.expression());
- if (StringUtil.isNotEmpty(expResult.getError())) {
- return expResult;
- }
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Mathematical OP: " + ctx.getText());
try {
- return MathematicalFunctionOp.doFunction1Op(expResult, opType, Integer.parseInt(ctx.parameter().INTEGER().getText()));
- } catch (IllegalExpressionException e) {
- ExpressionResult result = new ExpressionResult();
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError(e.getMessage());
- return result;
+ int opType = ctx.mathematical_operator1().getStart().getType();
+ ExpressionResult expResult = visit(ctx.expression());
+ if (StringUtil.isNotEmpty(expResult.getError())) {
+ return expResult;
+ }
+ try {
+ return MathematicalFunctionOp.doFunction1Op(expResult, opType, Integer.parseInt(ctx.parameter().INTEGER().getText()));
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ }
+ } finally {
+ traceContext.stopSpan(span);
}
}
@Override
public ExpressionResult visitTopNOP(MQEParser.TopNOPContext ctx) {
- return visit(ctx.metric());
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE TopN OP: " + ctx.getText());
+ try {
+ return visit(ctx.metric());
+ } finally {
+ traceContext.stopSpan(span);
+ }
}
@Override
public ExpressionResult visitRelablesOP(MQEParser.RelablesOPContext ctx) {
- ExpressionResult result = visit(ctx.expression());
- if (!result.isLabeledResult()) {
- // Reserve the original result type
- result.setError("The result of expression [" + ctx.expression().getText() + "] is not a labeled result.");
- return result;
- }
- KeyValue targetLabel = buildLabel(ctx.label());
- KeyValue replaceLabel = buildLabel(ctx.replaceLabel().label());
- List<KeyValue> targetLabels = parseLabelValue(targetLabel, Const.COMMA);
- List<KeyValue> replaceLabels = parseLabelValue(replaceLabel, Const.COMMA);
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Relabels OP: " + ctx.getText());
+ try {
+ ExpressionResult result = visit(ctx.expression());
+ if (!result.isLabeledResult()) {
+ // Reserve the original result type
+ result.setError("The result of expression [" + ctx.expression().getText() + "] is not a labeled result.");
+ return result;
+ }
+ KeyValue targetLabel = buildLabel(ctx.label());
+ KeyValue replaceLabel = buildLabel(ctx.replaceLabel().label());
+ List<KeyValue> targetLabels = parseLabelValue(targetLabel, Const.COMMA);
+ List<KeyValue> replaceLabels = parseLabelValue(replaceLabel, Const.COMMA);
- Map<KeyValue, KeyValue> relabelMap = new HashMap<>();
- if (targetLabels.isEmpty() || replaceLabels.isEmpty()) {
- return result;
- }
- if (targetLabels.size() != replaceLabels.size()) {
- result.setError(
- "Targrt label [" + targetLabel.getKey() + "]: the number of relabel values is not equal to the number of replace label.");
- return result;
- }
- for (int i = 0; i < targetLabels.size(); i++) {
- relabelMap.put(targetLabels.get(i), replaceLabels.get(i));
- }
- for (MQEValues mqeValues : result.getResults()) {
- for (KeyValue label : mqeValues.getMetric().getLabels()) {
- if (relabelMap.containsKey(label)) {
- KeyValue replaceLabelValue = relabelMap.get(label);
- label.setKey(replaceLabelValue.getKey());
- label.setValue(replaceLabelValue.getValue());
+ Map<KeyValue, KeyValue> relabelMap = new HashMap<>();
+ if (targetLabels.isEmpty() || replaceLabels.isEmpty()) {
+ return result;
+ }
+ if (targetLabels.size() != replaceLabels.size()) {
+ result.setError(
+ "Target label [" + targetLabel.getKey() + "]: the number of relabel values is not equal to the number of replace label.");
+ return result;
+ }
+ for (int i = 0; i < targetLabels.size(); i++) {
+ relabelMap.put(targetLabels.get(i), replaceLabels.get(i));
+ }
+ for (MQEValues mqeValues : result.getResults()) {
+ for (KeyValue label : mqeValues.getMetric().getLabels()) {
+ if (relabelMap.containsKey(label)) {
+ KeyValue replaceLabelValue = relabelMap.get(label);
+ label.setKey(replaceLabelValue.getKey());
+ label.setValue(replaceLabelValue.getValue());
+ }
}
}
+ return result;
+ } finally {
+ traceContext.stopSpan(span);
}
- return result;
}
@Override
public ExpressionResult visitLogicalOperatorOP(MQEParser.LogicalOperatorOPContext ctx) {
- int opType = ctx.logical_operator().getStart().getType();
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Logical OP: " + ctx.getText());
try {
- return LogicalFunctionOp.doOP(opType, ctx.expressionList(), this);
- } catch (IllegalExpressionException e) {
- ExpressionResult result = new ExpressionResult();
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError(e.getMessage());
- return result;
+ int opType = ctx.logical_operator().getStart().getType();
+ try {
+ return LogicalFunctionOp.doOP(opType, ctx.expressionList(), this);
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ }
+ } finally {
+ traceContext.stopSpan(span);
}
}
@Override
public ExpressionResult visitCompareOp(MQEParser.CompareOpContext ctx) {
- ExpressionResult left = visit(ctx.expression(0));
- if (StringUtil.isNotBlank(left.getError())) {
- return left;
- }
- ExpressionResult right = visit(ctx.expression(1));
- if (StringUtil.isNotBlank(right.getError())) {
- return right;
- }
- int opType = ctx.compare().getStart().getType();
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Compare OP: " + ctx.getText());
try {
- ExpressionResult result = CompareOp.doCompareOP(left, right, opType);
- if (ctx.parent == null) {
- result.setBoolResult(true);
+ ExpressionResult left = visit(ctx.expression(0));
+ if (StringUtil.isNotBlank(left.getError())) {
+ return left;
}
- return result;
- } catch (IllegalExpressionException e) {
- ExpressionResult result = new ExpressionResult();
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError(e.getMessage());
- return result;
+ ExpressionResult right = visit(ctx.expression(1));
+ if (StringUtil.isNotBlank(right.getError())) {
+ return right;
+ }
+ int opType = ctx.compare().getStart().getType();
+ try {
+ ExpressionResult result = CompareOp.doCompareOP(left, right, opType);
+ if (ctx.parent == null) {
+ result.setBoolResult(true);
+ }
+ return result;
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ }
+ } finally {
+ traceContext.stopSpan(span);
}
}
@Override
public ExpressionResult visitTrendOP(MQEParser.TrendOPContext ctx) {
- int opType = ctx.trend().getStart().getType();
- int trendRange = Integer.parseInt(ctx.INTEGER().getText());
- if (trendRange < 1) {
- ExpressionResult result = new ExpressionResult();
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError("The trend range must be greater than 0.");
- return result;
- }
- ExpressionResult expResult = visit(ctx.metric());
- if (StringUtil.isNotEmpty(expResult.getError())) {
- return expResult;
- }
- if (expResult.getType() != ExpressionResultType.TIME_SERIES_VALUES) {
- expResult.setError("The result of expression [" + ctx.metric().getText() + "] is not a time series result.");
- return expResult;
- }
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Trend OP: " + ctx.getText());
try {
- return TrendOp.doTrendOp(expResult, opType, trendRange, queryStep);
- } catch (IllegalExpressionException e) {
- ExpressionResult result = new ExpressionResult();
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError(e.getMessage());
- return result;
+ int opType = ctx.trend().getStart().getType();
+ int trendRange = Integer.parseInt(ctx.INTEGER().getText());
+ if (trendRange < 1) {
+ return getErrorResult("The trend range must be greater than 0.");
+ }
+ ExpressionResult expResult = visit(ctx.metric());
+ if (StringUtil.isNotEmpty(expResult.getError())) {
+ return expResult;
+ }
+ if (expResult.getType() != ExpressionResultType.TIME_SERIES_VALUES) {
+ expResult.setError(
+ "The result of expression [" + ctx.metric().getText() + "] is not a time series result.");
+ return expResult;
+ }
+ try {
+ return TrendOp.doTrendOp(expResult, opType, trendRange, queryStep);
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ }
+ } finally {
+ traceContext.stopSpan(span);
}
}
@Override
public ExpressionResult visitSortValuesOP(MQEParser.SortValuesOPContext ctx) {
- ExpressionResult result = visit(ctx.expression());
- int order = ctx.order().getStart().getType();
- Optional<Integer> limit = Optional.empty();
- if (ctx.INTEGER() != null) {
- limit = Optional.of(Integer.valueOf(ctx.INTEGER().getText()));
- }
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Sort Values OP: " + ctx.getText());
try {
- return SortValuesOp.doSortValuesOp(result, limit, order);
- } catch (IllegalExpressionException e) {
- ExpressionResult errorResult = new ExpressionResult();
- errorResult.setType(ExpressionResultType.UNKNOWN);
- errorResult.setError(e.getMessage());
- return errorResult;
+ ExpressionResult result = visit(ctx.expression());
+ int order = ctx.order().getStart().getType();
+ Optional<Integer> limit = Optional.empty();
+ if (ctx.INTEGER() != null) {
+ limit = Optional.of(Integer.valueOf(ctx.INTEGER().getText()));
+ }
+ try {
+ return SortValuesOp.doSortValuesOp(result, limit, order);
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ }
+ } finally {
+ traceContext.stopSpan(span);
}
}
@Override
public ExpressionResult visitSortLabelValuesOP(MQEParser.SortLabelValuesOPContext ctx) {
- ExpressionResult result = visit(ctx.expression());
- int order = ctx.order().getStart().getType();
- List<String> labelNames = new ArrayList<>();
- for (MQEParser.LabelNameContext labelNameContext : ctx.labelNameList().labelName()) {
- labelNames.add(labelNameContext.getText());
- }
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Sort Label Values OP: " + ctx.getText());
try {
- return SortLabelValuesOp.doSortLabelValuesOp(result, order, labelNames);
- } catch (IllegalExpressionException e) {
- ExpressionResult errorResult = new ExpressionResult();
- errorResult.setType(ExpressionResultType.UNKNOWN);
- errorResult.setError(e.getMessage());
- return errorResult;
+ ExpressionResult result = visit(ctx.expression());
+ int order = ctx.order().getStart().getType();
+ List<String> labelNames = new ArrayList<>();
+ for (MQEParser.LabelNameContext labelNameContext : ctx.labelNameList().labelName()) {
+ labelNames.add(labelNameContext.getText());
+ }
+ try {
+ return SortLabelValuesOp.doSortLabelValuesOp(result, order, labelNames);
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ }
+ } finally {
+ traceContext.stopSpan(span);
}
}
@@ -386,4 +440,11 @@ public abstract class MQEVisitorBase extends MQEParserBaseVisitor<ExpressionResu
}
return labels;
}
+
+ protected ExpressionResult getErrorResult(String error) {
+ ExpressionResult result = new ExpressionResult();
+ result.setType(ExpressionResultType.UNKNOWN);
+ result.setError(error);
+ return result;
+ }
}
diff --git a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/type/ExpressionResult.java b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/type/ExpressionResult.java
index 8de0383a9c..350e1fd7fe 100644
--- a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/type/ExpressionResult.java
+++ b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/type/ExpressionResult.java
@@ -22,6 +22,7 @@ package org.apache.skywalking.mqe.rt.type;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
@Data
public class ExpressionResult {
@@ -30,4 +31,5 @@ public class ExpressionResult {
private String error;
private boolean isLabeledResult = false;
private boolean isBoolResult = false;
+ private DebuggingTrace debuggingTrace;
}
diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRule.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRule.java
index e5238719b7..6ca788412d 100644
--- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRule.java
+++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRule.java
@@ -38,9 +38,12 @@ import org.apache.skywalking.mqe.rt.grammar.MQEParser;
import org.apache.skywalking.mqe.rt.type.ExpressionResult;
import org.apache.skywalking.mqe.rt.type.ExpressionResultType;
import org.apache.skywalking.oap.server.core.alarm.provider.expr.rt.AlarmMQEVerifyVisitor;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
import org.apache.skywalking.oap.server.library.util.StringUtil;
+import static org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace.TRACE_CONTEXT;
+
@Data
@ToString
@EqualsAndHashCode
@@ -75,22 +78,29 @@ public class AlarmRule {
} catch (ParseCancellationException e) {
throw new IllegalExpressionException("Expression: " + expression + " error: " + e.getMessage());
}
- AlarmMQEVerifyVisitor visitor = new AlarmMQEVerifyVisitor();
- ExpressionResult parseResult = visitor.visit(tree);
- if (StringUtil.isNotBlank(parseResult.getError())) {
- throw new IllegalExpressionException("Expression: " + expression + " error: " + parseResult.getError());
- }
- if (!parseResult.isBoolResult()) {
- throw new IllegalExpressionException("Expression: " + expression + " root operation is not a Compare Operation.");
- }
- if (ExpressionResultType.SINGLE_VALUE != parseResult.getType()) {
- throw new IllegalExpressionException("Expression: " + expression + " is not a SINGLE_VALUE result expression.");
- }
+ try {
+ TRACE_CONTEXT.set(new DebuggingTraceContext(expression, false, false));
+ AlarmMQEVerifyVisitor visitor = new AlarmMQEVerifyVisitor();
+ ExpressionResult parseResult = visitor.visit(tree);
+ if (StringUtil.isNotBlank(parseResult.getError())) {
+ throw new IllegalExpressionException("Expression: " + expression + " error: " + parseResult.getError());
+ }
+ if (!parseResult.isBoolResult()) {
+ throw new IllegalExpressionException(
+ "Expression: " + expression + " root operation is not a Compare Operation.");
+ }
+ if (ExpressionResultType.SINGLE_VALUE != parseResult.getType()) {
+ throw new IllegalExpressionException(
+ "Expression: " + expression + " is not a SINGLE_VALUE result expression.");
+ }
- verifyIncludeMetrics(visitor.getIncludeMetrics(), expression);
- this.expression = expression;
- this.includeMetrics = visitor.getIncludeMetrics();
- this.maxTrendRange = visitor.getMaxTrendRange();
+ verifyIncludeMetrics(visitor.getIncludeMetrics(), expression);
+ this.expression = expression;
+ this.includeMetrics = visitor.getIncludeMetrics();
+ this.maxTrendRange = visitor.getMaxTrendRange();
+ } finally {
+ TRACE_CONTEXT.remove();
+ }
}
private void verifyIncludeMetrics(Set<String> includeMetrics, String expression) throws IllegalExpressionException {
diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRule.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRule.java
index 7bd3b6ea5e..4eb03d81bb 100644
--- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRule.java
+++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRule.java
@@ -43,6 +43,7 @@ import org.apache.skywalking.mqe.rt.type.ExpressionResult;
import org.apache.skywalking.mqe.rt.type.ExpressionResultType;
import org.apache.skywalking.mqe.rt.type.MQEValues;
import org.apache.skywalking.oap.server.core.alarm.provider.expr.rt.AlarmMQEVisitor;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.core.alarm.AlarmMessage;
import org.apache.skywalking.oap.server.core.alarm.MetaInAlarm;
@@ -59,6 +60,8 @@ import org.joda.time.Minutes;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
+import static org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace.TRACE_CONTEXT;
+
/**
* RunningRule represents each rule in running status. Based on the {@link AlarmRule} definition,
*/
@@ -345,52 +348,57 @@ public class RunningRule {
private boolean isMatch() {
int isMatch = 0;
- AlarmMQEVisitor visitor = new AlarmMQEVisitor(this.values, this.endTime, this.additionalPeriod);
- ExpressionResult parseResult = visitor.visit(exprTree);
- if (StringUtil.isNotBlank(parseResult.getError())) {
- log.error("expression:" + expression + " error: " + parseResult.getError());
- return false;
- }
- if (!parseResult.isBoolResult() ||
- ExpressionResultType.SINGLE_VALUE != parseResult.getType() ||
- CollectionUtils.isEmpty(parseResult.getResults())) {
- return false;
- }
- if (!parseResult.isLabeledResult()) {
- MQEValues mqeValues = parseResult.getResults().get(0);
- if (mqeValues != null &&
- CollectionUtils.isNotEmpty(mqeValues.getValues()) &&
- mqeValues.getValues().get(0) != null) {
- isMatch = (int) mqeValues.getValues().get(0).getDoubleValue();
+ try {
+ TRACE_CONTEXT.set(new DebuggingTraceContext(expression, false, false));
+ AlarmMQEVisitor visitor = new AlarmMQEVisitor(this.values, this.endTime, this.additionalPeriod);
+ ExpressionResult parseResult = visitor.visit(exprTree);
+ if (StringUtil.isNotBlank(parseResult.getError())) {
+ log.error("expression:" + expression + " error: " + parseResult.getError());
+ return false;
}
- } else {
- // if the result has multiple labels, when there is one label match, then the result is match
- // for example in 5 minutes, the sum(percentile{p='50,75'} > 1000) >= 3
- // percentile{p='50,75'} result is:
- // P50(1000,1100,1200,1000,500), > 1000 2 times
- // P75(2000,1500,1200,1000,500), > 1000 3 times
- // percentile{p='50,75'} > 1000 result is:
- // P50(0,1,1,0,0)
- // P75(1,1,1,0,0)
- // sum(percentile{p='50,75'} > 1000) >= 3 result is:
- // P50(0)
- // P75(1)
- // then the isMatch is 1
- for (MQEValues mqeValues : parseResult.getResults()) {
+ if (!parseResult.isBoolResult() ||
+ ExpressionResultType.SINGLE_VALUE != parseResult.getType() ||
+ CollectionUtils.isEmpty(parseResult.getResults())) {
+ return false;
+ }
+ if (!parseResult.isLabeledResult()) {
+ MQEValues mqeValues = parseResult.getResults().get(0);
if (mqeValues != null &&
CollectionUtils.isNotEmpty(mqeValues.getValues()) &&
mqeValues.getValues().get(0) != null) {
isMatch = (int) mqeValues.getValues().get(0).getDoubleValue();
- if (isMatch == 1) {
- break;
+ }
+ } else {
+ // if the result has multiple labels, when there is one label match, then the result is match
+ // for example in 5 minutes, the sum(percentile{p='50,75'} > 1000) >= 3
+ // percentile{p='50,75'} result is:
+ // P50(1000,1100,1200,1000,500), > 1000 2 times
+ // P75(2000,1500,1200,1000,500), > 1000 3 times
+ // percentile{p='50,75'} > 1000 result is:
+ // P50(0,1,1,0,0)
+ // P75(1,1,1,0,0)
+ // sum(percentile{p='50,75'} > 1000) >= 3 result is:
+ // P50(0)
+ // P75(1)
+ // then the isMatch is 1
+ for (MQEValues mqeValues : parseResult.getResults()) {
+ if (mqeValues != null &&
+ CollectionUtils.isNotEmpty(mqeValues.getValues()) &&
+ mqeValues.getValues().get(0) != null) {
+ isMatch = (int) mqeValues.getValues().get(0).getDoubleValue();
+ if (isMatch == 1) {
+ break;
+ }
}
}
}
+ if (log.isTraceEnabled()) {
+ log.trace("Match expression is {}", expression);
+ }
+ return isMatch == 1;
+ } finally {
+ TRACE_CONTEXT.remove();
}
- if (log.isTraceEnabled()) {
- log.trace("Match expression is {}", expression);
- }
- return isMatch == 1;
}
public boolean isExpired() {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AggregationQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AggregationQueryService.java
index bac6dfbb99..e065a7e408 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AggregationQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AggregationQueryService.java
@@ -22,6 +22,9 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.core.Const;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
@@ -53,7 +56,7 @@ public class AggregationQueryService implements Service {
return aggregationQueryDAO;
}
- public List<SelectedRecord> sortMetrics(TopNCondition condition, Duration duration) throws IOException {
+ private List<SelectedRecord> invokeSortMetrics(TopNCondition condition, Duration duration) throws IOException {
if (!condition.senseScope()) {
return Collections.emptyList();
}
@@ -109,4 +112,21 @@ public class AggregationQueryService implements Service {
});
return selectedRecords;
}
+
+ public List<SelectedRecord> sortMetrics(TopNCondition condition,
+ Duration duration) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Service: sortMetrics");
+ span.setMsg("TopNCondition: " + condition + ", Duration: " + duration);
+ }
+ return invokeSortMetrics(condition, duration);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetricsQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetricsQueryService.java
index 375c8b5e4e..d8035b9446 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetricsQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetricsQueryService.java
@@ -30,12 +30,16 @@ import org.apache.skywalking.oap.server.core.query.type.KVInt;
import org.apache.skywalking.oap.server.core.query.type.KeyValue;
import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
import org.apache.skywalking.oap.server.core.query.type.NullableValue;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.module.Service;
+import static org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace.TRACE_CONTEXT;
+
@Slf4j
public class MetricsQueryService implements Service {
private final ModuleManager moduleManager;
@@ -72,10 +76,7 @@ public class MetricsQueryService implements Service {
return new NullableValue(defaultValue, true);
}
- /**
- * Read time-series values in the duration of required metrics
- */
- public MetricsValues readMetricsValues(MetricsCondition condition, Duration duration) throws IOException {
+ private MetricsValues invokeReadMetricsValues(MetricsCondition condition, Duration duration) throws IOException {
if (!condition.senseScope() || !condition.getEntity().isValid()) {
return new MetricsValues();
}
@@ -84,11 +85,25 @@ public class MetricsQueryService implements Service {
}
/**
- * Read value in the given time duration, usually as a linear.
- *
- * @param labels the labels you need to query.
+ * Read time-series values in the duration of required metrics
*/
- public List<MetricsValues> readLabeledMetricsValues(MetricsCondition condition,
+ public MetricsValues readMetricsValues(MetricsCondition condition, Duration duration) throws IOException {
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Service");
+ span.setMsg("readMetricsValues, MetricsCondition: " + condition + ", Duration: " + duration);
+ }
+ return invokeReadMetricsValues(condition, duration);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
+ private List<MetricsValues> invokeReadLabeledMetricsValues(MetricsCondition condition,
List<KeyValue> labels,
Duration duration) throws IOException {
if (!condition.senseScope() || !condition.getEntity().isValid()) {
@@ -98,6 +113,29 @@ public class MetricsQueryService implements Service {
condition, ValueColumnMetadata.INSTANCE.getValueCName(condition.getName()), labels, duration);
}
+ /**
+ * Read value in the given time duration, usually as a linear.
+ *
+ * @param labels the labels you need to query.
+ */
+ public List<MetricsValues> readLabeledMetricsValues(MetricsCondition condition,
+ List<KeyValue> labels,
+ Duration duration) throws IOException {
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Service");
+ span.setMsg("readLabeledMetricsValues, MetricsCondition: " + condition + ", Labels: " + labels + ", Duration: " + duration);
+ }
+ return invokeReadLabeledMetricsValues(condition, labels, duration);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
public List<MetricsValues> readLabeledMetricsValuesWithoutEntity(String metricsName,
List<KeyValue> labels,
Duration duration) throws IOException {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/RecordQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/RecordQueryService.java
index c645909ec4..759e57fc59 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/RecordQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/RecordQueryService.java
@@ -22,6 +22,8 @@ import java.util.Collections;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
import org.apache.skywalking.oap.server.core.query.type.Record;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
@@ -31,6 +33,8 @@ import org.apache.skywalking.oap.server.library.module.Service;
import java.io.IOException;
import java.util.List;
+import static org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace.TRACE_CONTEXT;
+
public class RecordQueryService implements Service {
private final ModuleManager moduleManager;
private IRecordsQueryDAO recordsQueryDAO;
@@ -48,11 +52,27 @@ public class RecordQueryService implements Service {
return recordsQueryDAO;
}
- public List<Record> readRecords(RecordCondition condition, Duration duration) throws IOException {
+ private List<Record> invokeReadRecords(RecordCondition condition, Duration duration) throws IOException {
if (!condition.senseScope() || !condition.getParentEntity().isValid()) {
return Collections.emptyList();
}
return getRecordsQueryDAO().readRecords(
condition, ValueColumnMetadata.INSTANCE.getValueCName(condition.getName()), duration);
}
+
+ public List<Record> readRecords(RecordCondition condition, Duration duration) throws IOException {
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Service");
+ span.setMsg("readRecords, RecordCondition: " + condition + ", Duration: " + duration);
+ }
+ return invokeReadRecords(condition, duration);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java
index ff71638e1b..eecbc3a596 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.query.input;
import lombok.Getter;
import lombok.Setter;
+import lombok.ToString;
import org.apache.skywalking.oap.server.core.query.DurationUtils;
import org.apache.skywalking.oap.server.core.query.PointOfTime;
import org.apache.skywalking.oap.server.core.query.enumeration.Step;
@@ -28,6 +29,7 @@ import java.util.List;
@Getter
@Setter
+@ToString
public class Duration {
private String start;
private String end;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Entity.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Entity.java
index d7864fedf2..f440419017 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Entity.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Entity.java
@@ -21,6 +21,7 @@ package org.apache.skywalking.oap.server.core.query.input;
import java.util.Objects;
import lombok.Getter;
import lombok.Setter;
+import lombok.ToString;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
@@ -31,6 +32,7 @@ import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
*/
@Setter
@Getter
+@ToString
public class Entity {
/**
* <pre>
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/MetricsCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/MetricsCondition.java
index 53a2a0abec..2c5bd6650d 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/MetricsCondition.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/MetricsCondition.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.query.input;
import lombok.Getter;
import lombok.Setter;
+import lombok.ToString;
import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
import org.apache.skywalking.oap.server.core.query.enumeration.MetricsType;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
@@ -29,6 +30,7 @@ import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetad
*/
@Getter
@Setter
+@ToString
public class MetricsCondition {
/**
* Metrics name
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/RecordCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/RecordCondition.java
index eab7a1de3e..2a620a94c6 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/RecordCondition.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/RecordCondition.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.query.input;
import lombok.Getter;
import lombok.Setter;
+import lombok.ToString;
import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
import org.apache.skywalking.oap.server.core.query.enumeration.MetricsType;
import org.apache.skywalking.oap.server.core.query.enumeration.Order;
@@ -34,6 +35,7 @@ import org.apache.skywalking.oap.server.library.util.StringUtil;
*/
@Setter
@Getter
+@ToString
public class RecordCondition {
/**
* Metrics name
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TopNCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TopNCondition.java
index 8ced87aead..33f2984277 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TopNCondition.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TopNCondition.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.query.input;
import lombok.Getter;
import lombok.Setter;
+import lombok.ToString;
import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
import org.apache.skywalking.oap.server.core.query.enumeration.MetricsType;
import org.apache.skywalking.oap.server.core.query.enumeration.Order;
@@ -33,6 +34,7 @@ import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetad
*/
@Setter
@Getter
+@ToString
public class TopNCondition {
/**
* Metrics name
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
index 419776a955..85dcc8eb02 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
@@ -20,9 +20,11 @@ package org.apache.skywalking.oap.server.core.query.type;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import lombok.ToString;
@Data
@EqualsAndHashCode
+@ToString
public class KeyValue {
private String key;
private String value;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/debugging/DebuggingSpan.java
similarity index 52%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
copy to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/debugging/DebuggingSpan.java
index 419776a955..7b836aca0a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/debugging/DebuggingSpan.java
@@ -16,22 +16,36 @@
*
*/
-package org.apache.skywalking.oap.server.core.query.type;
+package org.apache.skywalking.oap.server.core.query.type.debugging;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
-@Data
-@EqualsAndHashCode
-public class KeyValue {
- private String key;
- private String value;
+@Getter
+public class DebuggingSpan {
+ private final int spanId;
+ @Setter
+ private int parentSpanId;
+ private final String operation;
+ //nano seconds
+ private final long startTime;
+ //nano seconds
+ private long endTime;
+ //nano seconds
+ private long duration;
+ @Setter
+ private String msg;
+ @Setter
+ private String error;
- public KeyValue(String key, String value) {
- this.key = key;
- this.value = value;
+ public DebuggingSpan(int spanId, String operation) {
+ this.spanId = spanId;
+ this.operation = operation;
+ this.startTime = System.nanoTime();
}
- public KeyValue() {
+ public void stopSpan() {
+ this.endTime = System.nanoTime();
+ this.duration = endTime - startTime;
}
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/debugging/DebuggingTrace.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/debugging/DebuggingTrace.java
new file mode 100644
index 0000000000..3159e67cdc
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/debugging/DebuggingTrace.java
@@ -0,0 +1,50 @@
+/*
+ * 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.skywalking.oap.server.core.query.type.debugging;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import lombok.Getter;
+
+@Getter
+public class DebuggingTrace {
+ public final static ThreadLocal<DebuggingTraceContext> TRACE_CONTEXT = new ThreadLocal<>();
+ private final String traceId;
+ private final String condition;
+ private final long startTime;
+ private long endTime;
+ private long duration;
+ private final List<DebuggingSpan> spans = new ArrayList<>();
+
+ public DebuggingTrace(String condition) {
+ this.condition = condition;
+ this.traceId = UUID.randomUUID().toString();
+ this.startTime = System.nanoTime();
+ }
+
+ public void addSpan(DebuggingSpan span) {
+ spans.add(span);
+ }
+
+ public void stopTrace() {
+ this.endTime = System.nanoTime();
+ this.duration = endTime - startTime;
+ }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/debugging/DebuggingTraceContext.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/debugging/DebuggingTraceContext.java
new file mode 100644
index 0000000000..5f1e9e7996
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/debugging/DebuggingTraceContext.java
@@ -0,0 +1,68 @@
+/*
+ * 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.skywalking.oap.server.core.query.type.debugging;
+
+import java.util.Stack;
+import lombok.Getter;
+
+@Getter
+public class DebuggingTraceContext {
+ private final DebuggingTrace execTrace;
+ private final Stack<DebuggingSpan> spanStack = new Stack<>();
+ private int spanIdGenerator;
+ private final boolean debug;
+ private final boolean dumpStorageRsp;
+
+ public DebuggingTraceContext(String condition, boolean debug, boolean dumpStorageRsp) {
+ this.execTrace = new DebuggingTrace(condition);
+ this.debug = debug;
+ this.dumpStorageRsp = dumpStorageRsp;
+ }
+
+ public DebuggingSpan createSpan(String operation) {
+ DebuggingSpan span = new DebuggingSpan(spanIdGenerator++, operation);
+ if (debug) {
+ DebuggingSpan parentSpan = spanStack.isEmpty() ? null : spanStack.peek();
+ if (parentSpan != null) {
+ span.setParentSpanId(parentSpan.getSpanId());
+ } else {
+ span.setParentSpanId(-1);
+ }
+ spanStack.push(span);
+ execTrace.addSpan(span);
+ }
+ return span;
+ }
+
+ public void stopSpan(DebuggingSpan span) {
+ if (debug) {
+ span.stopSpan();
+ if (spanStack.isEmpty()) {
+ return;
+ }
+ spanStack.pop();
+ }
+ }
+
+ public void stopTrace() {
+ if (debug) {
+ execTrace.stopTrace();
+ }
+ }
+}
diff --git a/oap-server/server-query-plugin/debugging-query-plugin/pom.xml b/oap-server/server-query-plugin/debugging-query-plugin/pom.xml
index b67b392902..99965098fd 100644
--- a/oap-server/server-query-plugin/debugging-query-plugin/pom.xml
+++ b/oap-server/server-query-plugin/debugging-query-plugin/pom.xml
@@ -34,5 +34,10 @@
<artifactId>server-core</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.skywalking</groupId>
+ <artifactId>query-graphql-plugin</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git a/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingHTTPHandler.java b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingHTTPHandler.java
index cd6ef86f5f..3c41d1a2f2 100644
--- a/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingHTTPHandler.java
+++ b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingHTTPHandler.java
@@ -18,15 +18,32 @@
package org.apache.skywalking.oap.query.debug;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.linecorp.armeria.server.annotation.Get;
+import com.linecorp.armeria.server.annotation.Param;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.mqe.rt.type.ExpressionResult;
+import org.apache.skywalking.oap.query.debug.mqe.DebuggingMQERsp;
+import org.apache.skywalking.oap.query.graphql.resolver.MetricsExpressionQuery;
import org.apache.skywalking.oap.server.core.CoreModule;
+import org.apache.skywalking.oap.server.core.analysis.Layer;
+import org.apache.skywalking.oap.server.core.query.enumeration.Step;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.Entity;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
import org.apache.skywalking.oap.server.core.status.ServerStatusService;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
@Slf4j
public class DebuggingHTTPHandler {
private final ServerStatusService serverStatusService;
+ private final MetricsExpressionQuery mqeQuery;
final DebuggingQueryConfig config;
public DebuggingHTTPHandler(final ModuleManager manager, final DebuggingQueryConfig config) {
@@ -34,10 +51,82 @@ public class DebuggingHTTPHandler {
.provider()
.getService(ServerStatusService.class);
this.config = config;
+ this.mqeQuery = new MetricsExpressionQuery(manager);
}
@Get("/debugging/config/dump")
public String dumpConfigurations() {
return serverStatusService.dumpBootingConfigurations(config.getKeywords4MaskingSecretsOfConfig());
}
+
+ @SneakyThrows
+ @Get("/debugging/query/mqe")
+ public String execExpression(@Param("dumpDBRsp") boolean dumpStorageRsp,
+ @Param("expression") String expression,
+ @Param("startTime") String startTime,
+ @Param("endTime") String endTime,
+ @Param("step") String step,
+ @Param("service") String service,
+ @Param("serviceLayer") String serviceLayer,
+ @Param("serviceInstance") Optional<String> serviceInstance,
+ @Param("endpoint") Optional<String> endpoint,
+ @Param("process") Optional<String> process,
+ @Param("destService") Optional<String> destService,
+ @Param("destServiceLayer") Optional<String> destServiceLayer,
+ @Param("destServiceInstance") Optional<String> destServiceInstance,
+ @Param("destEndpoint") Optional<String> destEndpoint,
+ @Param("destProcess") Optional<String> destProcess
+ ) {
+ Entity entity = new Entity();
+ entity.setServiceName(service);
+ entity.setServiceInstanceName(serviceInstance.orElse(null));
+ entity.setEndpointName(endpoint.orElse(null));
+ entity.setProcessName(process.orElse(null));
+ entity.setDestServiceName(destService.orElse(null));
+ entity.setDestServiceInstanceName(destServiceInstance.orElse(null));
+ entity.setDestEndpointName(destEndpoint.orElse(null));
+ entity.setDestProcessName(destProcess.orElse(null));
+ entity.setNormal(Layer.nameOf(serviceLayer).isNormal());
+ destServiceLayer.ifPresent(layer -> {
+ entity.setDestNormal(Layer.nameOf(layer).isNormal());
+ });
+ Duration duration = new Duration();
+ duration.setStart(startTime);
+ duration.setEnd(endTime);
+ duration.setStep(Step.valueOf(step));
+ ExpressionResult expressionResult = mqeQuery.execExpression(expression, entity, duration, true, dumpStorageRsp);
+ DebuggingTrace execTrace = expressionResult.getDebuggingTrace();
+
+ Map<Integer, DebuggingSpanRsp> spanMap = execTrace.getSpans().stream()
+ .collect(Collectors.toMap(
+ DebuggingSpan::getSpanId,
+ this::transformSpan
+ ));
+
+ execTrace.getSpans().forEach(span -> {
+ if (span.getParentSpanId() != -1) {
+ DebuggingSpanRsp parentSpan = spanMap.get(span.getParentSpanId());
+ parentSpan.getChildSpans().add(spanMap.get(span.getSpanId()));
+ }
+ });
+ DebuggingMQERsp result = new DebuggingMQERsp(
+ expressionResult.getType(), expressionResult.getResults(), expressionResult.getError(),
+ new DebuggingTraceRsp(
+ execTrace.getTraceId(), execTrace.getCondition(), execTrace.getStartTime(), execTrace.getEndTime(),
+ execTrace.getDuration(), spanMap.get(0)
+ )
+ );
+
+ YAMLFactory yamlFactory = new YAMLFactory();
+ ObjectMapper mapper = new ObjectMapper(yamlFactory);
+
+ return mapper.writeValueAsString(result);
+ }
+
+ private DebuggingSpanRsp transformSpan(DebuggingSpan span) {
+ return new DebuggingSpanRsp(
+ span.getSpanId(), span.getParentSpanId(), span.getOperation(), span.getStartTime(), span.getEndTime(),
+ span.getDuration(), span.getMsg(), span.getError()
+ );
+ }
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingSpanRsp.java
similarity index 59%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
copy to oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingSpanRsp.java
index 419776a955..0d62d84063 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
+++ b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingSpanRsp.java
@@ -16,22 +16,23 @@
*
*/
-package org.apache.skywalking.oap.server.core.query.type;
+package org.apache.skywalking.oap.query.debug;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
-@Data
-@EqualsAndHashCode
-public class KeyValue {
- private String key;
- private String value;
-
- public KeyValue(String key, String value) {
- this.key = key;
- this.value = value;
- }
-
- public KeyValue() {
- }
+@RequiredArgsConstructor
+@Getter
+public class DebuggingSpanRsp {
+ private final int spanId;
+ private final int parentSpanId;
+ private final String operation;
+ private final long startTime;
+ private final long endTime;
+ private final long duration;
+ private final String msg;
+ private final String error;
+ private final List<DebuggingSpanRsp> childSpans = new ArrayList<>();
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingTraceRsp.java
similarity index 67%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
copy to oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingTraceRsp.java
index 419776a955..aa77970913 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
+++ b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingTraceRsp.java
@@ -16,22 +16,18 @@
*
*/
-package org.apache.skywalking.oap.server.core.query.type;
+package org.apache.skywalking.oap.query.debug;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
-@Data
-@EqualsAndHashCode
-public class KeyValue {
- private String key;
- private String value;
-
- public KeyValue(String key, String value) {
- this.key = key;
- this.value = value;
- }
-
- public KeyValue() {
- }
+@RequiredArgsConstructor
+@Getter
+public class DebuggingTraceRsp {
+ private final String traceId;
+ private final String condition;
+ private final long startTime;
+ private final long endTime;
+ private final long duration;
+ private final DebuggingSpanRsp rootSpan;
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/mqe/DebuggingMQERsp.java
similarity index 59%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
copy to oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/mqe/DebuggingMQERsp.java
index 419776a955..e8002bda33 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
+++ b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/mqe/DebuggingMQERsp.java
@@ -16,22 +16,20 @@
*
*/
-package org.apache.skywalking.oap.server.core.query.type;
+package org.apache.skywalking.oap.query.debug.mqe;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
+import java.util.List;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.skywalking.mqe.rt.type.ExpressionResultType;
+import org.apache.skywalking.mqe.rt.type.MQEValues;
+import org.apache.skywalking.oap.query.debug.DebuggingTraceRsp;
-@Data
-@EqualsAndHashCode
-public class KeyValue {
- private String key;
- private String value;
-
- public KeyValue(String key, String value) {
- this.key = key;
- this.value = value;
- }
-
- public KeyValue() {
- }
+@RequiredArgsConstructor
+@Getter
+public class DebuggingMQERsp {
+ private final ExpressionResultType type;
+ private final List<MQEValues> results;
+ private final String error;
+ private final DebuggingTraceRsp execTrace;
}
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java
index 5a83f17aed..8d62ef48bb 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java
@@ -47,6 +47,8 @@ import org.apache.skywalking.oap.server.core.query.type.KeyValue;
import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
import org.apache.skywalking.oap.server.core.query.type.Record;
import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
@@ -55,6 +57,8 @@ import org.apache.skywalking.mqe.rt.type.ExpressionResult;
import org.apache.skywalking.mqe.rt.type.ExpressionResultType;
import org.joda.time.DateTime;
+import static org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace.TRACE_CONTEXT;
+
@Slf4j
public class MQEVisitor extends MQEVisitorBase {
private final Entity entity;
@@ -102,77 +106,76 @@ public class MQEVisitor extends MQEVisitorBase {
@Override
public ExpressionResult visitMetric(MQEParser.MetricContext ctx) {
- ExpressionResult result = new ExpressionResult();
- String metricName = ctx.metricName().getText();
- Optional<ValueColumnMetadata.ValueColumn> valueColumn = ValueColumnMetadata.INSTANCE.readValueColumnDefinition(
- metricName);
- if (valueColumn.isEmpty()) {
- result.setType(ExpressionResultType.UNKNOWN);
- result.setError("Metric: [" + metricName + "] dose not exist.");
- return result;
- }
-
- Column.ValueDataType dataType = valueColumn.get().getDataType();
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Metric OP: " + ctx.getText());
try {
- if (Column.ValueDataType.COMMON_VALUE == dataType) {
- if (ctx.parent instanceof MQEParser.TopNOPContext) {
- MQEParser.TopNOPContext parent = (MQEParser.TopNOPContext) ctx.parent;
- int topN = Integer.parseInt(parent.INTEGER().getText());
- if (topN <= 0) {
- throw new IllegalExpressionException("TopN value must be > 0.");
+ ExpressionResult result = new ExpressionResult();
+ String metricName = ctx.metricName().getText();
+ Optional<ValueColumnMetadata.ValueColumn> valueColumn = ValueColumnMetadata.INSTANCE.readValueColumnDefinition(
+ metricName);
+ if (valueColumn.isEmpty()) {
+ result.setType(ExpressionResultType.UNKNOWN);
+ result.setError("Metric: [" + metricName + "] dose not exist.");
+ return result;
+ }
+
+ Column.ValueDataType dataType = valueColumn.get().getDataType();
+ try {
+ if (Column.ValueDataType.COMMON_VALUE == dataType) {
+ if (ctx.parent instanceof MQEParser.TopNOPContext) {
+ MQEParser.TopNOPContext parent = (MQEParser.TopNOPContext) ctx.parent;
+ int topN = Integer.parseInt(parent.INTEGER().getText());
+ if (topN <= 0) {
+ throw new IllegalExpressionException("TopN value must be > 0.");
+ }
+ querySortMetrics(metricName, Integer.parseInt(parent.INTEGER().getText()),
+ Order.valueOf(parent.order().getText().toUpperCase()), result);
+ } else if (ctx.parent instanceof MQEParser.TrendOPContext) {
+ //trend query requires get previous data according to the trend range
+ MQEParser.TrendOPContext parent = (MQEParser.TrendOPContext) ctx.parent;
+ int trendRange = Integer.parseInt(parent.INTEGER().getText());
+ queryMetrics(metricName, getTrendQueryDuration(trendRange), result);
+ } else {
+ queryMetrics(metricName, this.duration, result);
}
- querySortMetrics(metricName, Integer.parseInt(parent.INTEGER().getText()),
- Order.valueOf(parent.order().getText().toUpperCase()), result
- );
- } else if (ctx.parent instanceof MQEParser.TrendOPContext) {
- //trend query requires get previous data according to the trend range
- MQEParser.TrendOPContext parent = (MQEParser.TrendOPContext) ctx.parent;
- int trendRange = Integer.parseInt(parent.INTEGER().getText());
- queryMetrics(metricName, getTrendQueryDuration(trendRange), result);
- } else {
- queryMetrics(metricName, this.duration, result);
- }
- } else if (Column.ValueDataType.LABELED_VALUE == dataType) {
- if (ctx.parent instanceof MQEParser.TopNOPContext) {
- throw new IllegalExpressionException(
- "Metric: [" + metricName + "] is labeled value, dose not support top_n query.");
- }
- List<KeyValue> queryLabels = super.buildLabels(ctx.labelList());
- if (ctx.parent instanceof MQEParser.TrendOPContext) {
- MQEParser.TrendOPContext parent = (MQEParser.TrendOPContext) ctx.parent;
- int trendRange = Integer.parseInt(parent.INTEGER().getText());
- queryLabeledMetrics(metricName, queryLabels, getTrendQueryDuration(trendRange), result);
- } else {
- queryLabeledMetrics(metricName, queryLabels, this.duration, result);
- }
- } else if (Column.ValueDataType.SAMPLED_RECORD == dataType) {
- if (ctx.parent instanceof MQEParser.TopNOPContext) {
- MQEParser.TopNOPContext parent = (MQEParser.TopNOPContext) ctx.parent;
- int topN = Integer.parseInt(parent.INTEGER().getText());
- if (topN <= 0) {
- throw new IllegalExpressionException("TopN value must be > 0.");
+ } else if (Column.ValueDataType.LABELED_VALUE == dataType) {
+ if (ctx.parent instanceof MQEParser.TopNOPContext) {
+ throw new IllegalExpressionException(
+ "Metric: [" + metricName + "] is labeled value, dose not support top_n query.");
+ }
+ List<KeyValue> queryLabels = super.buildLabels(ctx.labelList());
+ if (ctx.parent instanceof MQEParser.TrendOPContext) {
+ MQEParser.TrendOPContext parent = (MQEParser.TrendOPContext) ctx.parent;
+ int trendRange = Integer.parseInt(parent.INTEGER().getText());
+ queryLabeledMetrics(metricName, queryLabels, getTrendQueryDuration(trendRange), result);
+ } else {
+ queryLabeledMetrics(metricName, queryLabels, this.duration, result);
+ }
+ } else if (Column.ValueDataType.SAMPLED_RECORD == dataType) {
+ if (ctx.parent instanceof MQEParser.TopNOPContext) {
+ MQEParser.TopNOPContext parent = (MQEParser.TopNOPContext) ctx.parent;
+ int topN = Integer.parseInt(parent.INTEGER().getText());
+ if (topN <= 0) {
+ throw new IllegalExpressionException("TopN value must be > 0.");
+ }
+ queryRecords(metricName, Integer.parseInt(parent.INTEGER().getText()),
+ Order.valueOf(parent.order().getText().toUpperCase()), result);
+ } else {
+ throw new IllegalExpressionException(
+ "Metric: [" + metricName + "] is topN record, need top_n function for query.");
}
- queryRecords(metricName, Integer.parseInt(parent.INTEGER().getText()),
- Order.valueOf(parent.order().getText().toUpperCase()), result
- );
- } else {
- throw new IllegalExpressionException(
- "Metric: [" + metricName + "] is topN record, need top_n function for query.");
}
+ } catch (IllegalExpressionException e) {
+ return getErrorResult(e.getMessage());
+ } catch (IOException e) {
+ ExpressionResult errorResult = getErrorResult("Internal IO exception, query metrics error.");
+ log.error("Query metrics from backend error.", e);
+ return errorResult;
}
- } catch (IllegalExpressionException e) {
- ExpressionResult errorResult = new ExpressionResult();
- errorResult.setType(ExpressionResultType.UNKNOWN);
- errorResult.setError(e.getMessage());
- return errorResult;
- } catch (IOException e) {
- ExpressionResult errorResult = new ExpressionResult();
- errorResult.setType(ExpressionResultType.UNKNOWN);
- errorResult.setError("Internal IO exception, query metrics error.");
- log.error("Query metrics from backend error.", e);
- return errorResult;
+ return result;
+ } finally {
+ traceContext.stopSpan(span);
}
- return result;
}
private void querySortMetrics(String metricName,
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsExpressionQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsExpressionQuery.java
index 1522278fb1..37a45b654f 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsExpressionQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsExpressionQuery.java
@@ -30,10 +30,15 @@ import org.apache.skywalking.mqe.rt.type.ExpressionResult;
import org.apache.skywalking.mqe.rt.type.ExpressionResultType;
import org.apache.skywalking.oap.server.core.query.input.Entity;
import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.mqe.rt.grammar.MQELexer;
import org.apache.skywalking.mqe.rt.grammar.MQEParser;
+import static org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace.TRACE_CONTEXT;
+
public class MetricsExpressionQuery implements GraphQLQueryResolver {
private final ModuleManager moduleManager;
private final DecimalFormat valueFormat = new DecimalFormat();
@@ -43,32 +48,53 @@ public class MetricsExpressionQuery implements GraphQLQueryResolver {
this.valueFormat.setGroupingUsed(false);
}
- public ExpressionResult execExpression(String expression, Entity entity, Duration duration) {
- MQELexer lexer = new MQELexer(
- CharStreams.fromString(expression));
- lexer.addErrorListener(new ParseErrorListener());
- MQEParser parser = new MQEParser(new CommonTokenStream(lexer));
- parser.addErrorListener(new ParseErrorListener());
- ParseTree tree;
+ public ExpressionResult execExpression(String expression,
+ Entity entity,
+ Duration duration,
+ boolean debug,
+ boolean dumpStorageRsp) {
+ DebuggingTraceContext traceContext = new DebuggingTraceContext(
+ "Expression: " + expression + ", Entity: " + entity + ", Duration: " + duration, debug, dumpStorageRsp);
+ TRACE_CONTEXT.set(traceContext);
+ DebuggingSpan span = traceContext.createSpan("MQE query");
try {
- tree = parser.expression();
- } catch (ParseCancellationException e) {
- ExpressionResult errorResult = new ExpressionResult();
- errorResult.setType(ExpressionResultType.UNKNOWN);
- errorResult.setError(e.getMessage());
- return errorResult;
- }
- MQEVisitor visitor = new MQEVisitor(moduleManager, entity, duration);
- ExpressionResult parseResult = visitor.visit(tree);
-
- parseResult.getResults().forEach(mqeValues -> {
- mqeValues.getValues().forEach(mqeValue -> {
- if (!mqeValue.isEmptyValue()) {
- mqeValue.setValue(valueFormat.format(mqeValue.getDoubleValue()));
+ MQEVisitor visitor = new MQEVisitor(moduleManager, entity, duration);
+ DebuggingTrace execTrace = traceContext.getExecTrace();
+ DebuggingSpan syntaxSpan = traceContext.createSpan("MQE syntax analysis");
+ ParseTree tree;
+ try {
+ MQELexer lexer = new MQELexer(
+ CharStreams.fromString(expression));
+ lexer.addErrorListener(new ParseErrorListener());
+ MQEParser parser = new MQEParser(new CommonTokenStream(lexer));
+ parser.addErrorListener(new ParseErrorListener());
+ try {
+ tree = parser.expression();
+ } catch (ParseCancellationException e) {
+ ExpressionResult errorResult = new ExpressionResult();
+ errorResult.setType(ExpressionResultType.UNKNOWN);
+ errorResult.setError(e.getMessage());
+ return errorResult;
}
+ } finally {
+ traceContext.stopSpan(syntaxSpan);
+ }
+ ExpressionResult parseResult = visitor.visit(tree);
+ parseResult.getResults().forEach(mqeValues -> {
+ mqeValues.getValues().forEach(mqeValue -> {
+ if (!mqeValue.isEmptyValue()) {
+ mqeValue.setValue(valueFormat.format(mqeValue.getDoubleValue()));
+ }
+ });
});
- });
-
- return parseResult;
+ if (debug) {
+ parseResult.setDebuggingTrace(execTrace);
+ }
+ return parseResult;
+ } finally {
+ traceContext.stopSpan(span);
+ traceContext.stopTrace();
+ TRACE_CONTEXT.remove();
+ }
}
}
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
index e0be806ea4..b4a0234eda 160000
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
@@ -1 +1 @@
-Subproject commit e0be806ea4f5e5e324e4ba57c2ca414931d9e512
+Subproject commit b4a0234edab6c06e31cfac9c95f3ba16b20f7912
diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBAggregationQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBAggregationQueryDAO.java
index a83d0e68df..27d1c3e88e 100644
--- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBAggregationQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBAggregationQueryDAO.java
@@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.storage.plugin.banyandb;
import com.google.common.collect.ImmutableSet;
+import com.google.gson.Gson;
import org.apache.skywalking.banyandb.v1.client.DataPoint;
import org.apache.skywalking.banyandb.v1.client.MeasureQuery;
import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse;
@@ -30,6 +31,9 @@ import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
import org.apache.skywalking.oap.server.core.query.type.KeyValue;
import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.stream.AbstractBanyanDBDAO;
@@ -50,7 +54,27 @@ public class BanyanDBAggregationQueryDAO extends AbstractBanyanDBDAO implements
}
@Override
- public List<SelectedRecord> sortMetrics(TopNCondition condition, String valueColumnName, Duration duration, List<KeyValue> additionalConditions) throws IOException {
+ public List<SelectedRecord> sortMetrics(TopNCondition condition,
+ String valueColumnName,
+ Duration duration,
+ List<KeyValue> additionalConditions) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Dao: sortMetrics");
+ span.setMsg("TopNCondition: " + condition + ", valueColumnName: " + valueColumnName + ", duration: " + duration + ", additionalConditions: " + additionalConditions);
+
+ }
+ return invokeSortMetrics(condition, valueColumnName, duration, additionalConditions);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
+ private List<SelectedRecord> invokeSortMetrics(TopNCondition condition, String valueColumnName, Duration duration, List<KeyValue> additionalConditions) throws IOException {
final String modelName = condition.getName();
final TimestampRange timestampRange = new TimestampRange(duration.getStartTimestamp(), duration.getEndTimestamp());
MetadataRegistry.Schema schema = MetadataRegistry.INSTANCE.findMetadata(modelName, duration.getStep());
@@ -79,13 +103,7 @@ public class BanyanDBAggregationQueryDAO extends AbstractBanyanDBDAO implements
List<SelectedRecord> serverSideTopN(TopNCondition condition, MetadataRegistry.Schema schema, MetadataRegistry.ColumnSpec valueColumnSpec,
TimestampRange timestampRange, List<KeyValue> additionalConditions) throws IOException {
- TopNQueryResponse resp = null;
- if (condition.getOrder() == Order.DES) {
- resp = topN(schema, timestampRange, condition.getTopN(), additionalConditions);
- } else {
- resp = bottomN(schema, timestampRange, condition.getTopN(), additionalConditions);
- }
-
+ TopNQueryResponse resp = traceServerSideTopN(schema, timestampRange, condition.getTopN(), additionalConditions, condition.getOrder());
if (resp.size() == 0) {
return Collections.emptyList();
} else if (resp.size() > 1) { // since we have done aggregation, i.e. MEAN
@@ -105,8 +123,8 @@ public class BanyanDBAggregationQueryDAO extends AbstractBanyanDBDAO implements
List<SelectedRecord> directMetricsTopN(TopNCondition condition, String valueColumnName, MetadataRegistry.ColumnSpec valueColumnSpec,
TimestampRange timestampRange, List<KeyValue> additionalConditions) throws IOException {
- MeasureQueryResponse resp = query(condition.getName(), TAGS, Collections.singleton(valueColumnName),
- timestampRange, new QueryBuilder<MeasureQuery>() {
+ MeasureQueryResponse resp = traceDirectMetricsTopN(condition.getName(), TAGS, Collections.singleton(valueColumnName),
+ timestampRange, valueColumnName, condition.getTopN(), condition.getOrder(), new QueryBuilder<MeasureQuery>() {
@Override
protected void apply(MeasureQuery query) {
query.meanBy(valueColumnName, ImmutableSet.of(Metrics.ENTITY_ID));
@@ -149,4 +167,90 @@ public class BanyanDBAggregationQueryDAO extends AbstractBanyanDBDAO implements
return String.valueOf(((Number) fieldValue).longValue());
}
}
+
+ private MeasureQueryResponse traceDirectMetricsTopN(String measureModelName,
+ Set<String> tags,
+ Set<String> fields,
+ TimestampRange timestampRange,
+ String valueColumnName,
+ int topN,
+ Order order,
+ QueryBuilder<MeasureQuery> queryBuilder) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ StringBuilder builder = new StringBuilder();
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query BanyanDB direct metrics TopN");
+ builder.append("Condition: ")
+ .append("measureModelName: ")
+ .append(measureModelName)
+ .append(", tags: ")
+ .append(tags)
+ .append(", fields: ")
+ .append(fields)
+ .append(", timestampRange: ")
+ .append(timestampRange)
+ .append(", valueColumnName: ")
+ .append(valueColumnName)
+ .append(", topN: ")
+ .append(topN)
+ .append(", order: ")
+ .append(order);
+ span.setMsg(builder.toString());
+ }
+ MeasureQueryResponse response = query(measureModelName, tags, fields, timestampRange, queryBuilder);
+ if (traceContext != null && traceContext.isDumpStorageRsp()) {
+ builder.append("\n").append(" Response: ").append(new Gson().toJson(response));
+ span.setMsg(builder.toString());
+ }
+ return response;
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
+ private TopNQueryResponse traceServerSideTopN(MetadataRegistry.Schema schema,
+ TimestampRange timestampRange,
+ int topN,
+ List<KeyValue> additionalConditions,
+ Order order) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ StringBuilder builder = new StringBuilder();
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query BanyanDB server-side TopN");
+ builder.append("Condition: ")
+ .append("schema: ")
+ .append(schema)
+ .append(", timestampRange: ")
+ .append(timestampRange)
+ .append(", topN: ")
+ .append(topN)
+ .append(", additionalConditions: ")
+ .append(additionalConditions)
+ .append(", order: ")
+ .append(order);
+ span.setMsg(builder.toString());
+ }
+ TopNQueryResponse response;
+ if (order == Order.DES) {
+ response = topN(schema, timestampRange, topN, additionalConditions);
+ } else {
+ response = bottomN(schema, timestampRange, topN, additionalConditions);
+ }
+ if (traceContext != null && traceContext.isDumpStorageRsp()) {
+ builder.append("\n").append(" Response: ").append(new Gson().toJson(response));
+ span.setMsg(builder.toString());
+ }
+ return response;
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
}
diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java
index 8bf59354bc..cf030fca22 100644
--- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java
@@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.storage.plugin.banyandb;
import com.google.common.collect.ImmutableSet;
+import com.google.gson.Gson;
import org.apache.skywalking.banyandb.v1.client.AbstractQuery;
import org.apache.skywalking.banyandb.v1.client.RowEntity;
import org.apache.skywalking.banyandb.v1.client.StreamQuery;
@@ -29,6 +30,9 @@ import org.apache.skywalking.oap.server.core.query.enumeration.Order;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
import org.apache.skywalking.oap.server.core.query.type.Record;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.stream.AbstractBanyanDBDAO;
@@ -48,11 +52,28 @@ public class BanyanDBRecordsQueryDAO extends AbstractBanyanDBDAO implements IRec
@Override
public List<Record> readRecords(RecordCondition condition, String valueColumnName, Duration duration) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query BanyanDB records");
+ span.setMsg(
+ "Condition: " + condition + ", ValueColumnName: " + valueColumnName + ", Duration: " + duration);
+ }
+ return invokeReadRecords(condition, valueColumnName, duration);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
+ public List<Record> invokeReadRecords(RecordCondition condition, String valueColumnName, Duration duration) throws IOException {
final String modelName = condition.getName();
final TimestampRange timestampRange = new TimestampRange(duration.getStartTimestamp(), duration.getEndTimestamp());
final Set<String> tags = ImmutableSet.of(TopN.ENTITY_ID, TopN.STATEMENT, TopN.TRACE_ID, valueColumnName);
- StreamQueryResponse resp = query(modelName, tags,
- timestampRange, new QueryBuilder<StreamQuery>() {
+ StreamQueryResponse resp = traceRecordsTopN(modelName, tags,
+ timestampRange, valueColumnName, condition.getTopN(), condition.getOrder(), new QueryBuilder<StreamQuery>() {
@Override
protected void apply(StreamQuery query) {
query.and(eq(TopN.ENTITY_ID, condition.getParentEntity().buildId()));
@@ -103,4 +124,45 @@ public class BanyanDBRecordsQueryDAO extends AbstractBanyanDBDAO implements IRec
return String.valueOf(((Number) e.getTagValue(fieldName)).longValue());
}
}
+
+ private StreamQueryResponse traceRecordsTopN(String modelName,
+ Set<String> tags,
+ TimestampRange timestampRange,
+ String valueColumnName,
+ int topN,
+ Order order,
+ QueryBuilder<StreamQuery> queryBuilder) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ StringBuilder builder = new StringBuilder();
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query BanyanDB records TopN");
+ builder.append("Condition: ")
+ .append(modelName)
+ .append(", Tags: ")
+ .append(tags)
+ .append(", TimestampRange: ")
+ .append(timestampRange)
+ .append(", ValueColumnName: ")
+ .append(valueColumnName)
+ .append(", TopN: ")
+ .append(topN)
+ .append(", Order: ")
+ .append(order);
+ span.setMsg(builder.toString());
+ }
+
+ StreamQueryResponse response = query(modelName, tags, timestampRange, queryBuilder);
+ if (traceContext != null && traceContext.isDumpStorageRsp()) {
+ builder.append("\n").append(" Response: ").append(new Gson().toJson(response));
+ span.setMsg(builder.toString());
+ }
+ return response;
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
}
diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/MetadataRegistry.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/MetadataRegistry.java
index bc3dc3de83..0f94173f4d 100644
--- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/MetadataRegistry.java
+++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/MetadataRegistry.java
@@ -624,6 +624,7 @@ public enum MetadataRegistry {
@Builder
@EqualsAndHashCode
+ @ToString
public static class Schema {
@Getter
private final SchemaMetadata metadata;
@@ -671,6 +672,7 @@ public enum MetadataRegistry {
@Builder
@EqualsAndHashCode
@Getter
+ @ToString
public static class TopNSpec {
private final String name;
@Singular
@@ -683,6 +685,7 @@ public enum MetadataRegistry {
@RequiredArgsConstructor
@Getter
+ @ToString
public static class ColumnSpec {
private final ColumnType columnType;
private final Class<?> columnClass;
diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsQueryDAO.java
index d64f674038..5a8375ebe9 100644
--- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsQueryDAO.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.measure;
import com.google.common.collect.ImmutableSet;
+import com.google.gson.Gson;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -27,6 +28,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.banyandb.v1.client.DataPoint;
import org.apache.skywalking.banyandb.v1.client.MeasureQuery;
@@ -44,6 +46,9 @@ import org.apache.skywalking.oap.server.core.query.type.IntValues;
import org.apache.skywalking.oap.server.core.query.type.KVInt;
import org.apache.skywalking.oap.server.core.query.type.KeyValue;
import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.BanyanDBStorageClient;
@@ -60,7 +65,47 @@ public class BanyanDBMetricsQueryDAO extends AbstractBanyanDBDAO implements IMet
}
@Override
- public MetricsValues readMetricsValues(MetricsCondition condition, String valueColumnName, Duration duration) throws IOException {
+ public MetricsValues readMetricsValues(MetricsCondition condition,
+ String valueColumnName,
+ Duration duration) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Dao: readMetricsValues");
+ span.setMsg(
+ "MetricsCondition: " + condition + ", valueColumnName: " + valueColumnName + ", duration: " + duration);
+ }
+ return invokeReadMetricsValues(condition, valueColumnName, duration);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
+ @Override
+ public List<MetricsValues> readLabeledMetricsValues(MetricsCondition condition,
+ String valueColumnName,
+ List<KeyValue> labels,
+ Duration duration) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Dao: readLabeledMetricsValues");
+ span.setMsg(
+ "MetricsCondition: " + condition + ", valueColumnName: " + valueColumnName + ", labels: " + labels + ", duration: " + duration);
+ }
+ return invokeReadLabeledMetricsValues(condition, valueColumnName, labels, duration);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
+ private MetricsValues invokeReadMetricsValues(MetricsCondition condition, String valueColumnName, Duration duration) throws IOException {
String modelName = condition.getName();
MetadataRegistry.Schema schema = MetadataRegistry.INSTANCE.findMetadata(modelName, duration.getStep());
if (schema == null) {
@@ -104,8 +149,7 @@ public class BanyanDBMetricsQueryDAO extends AbstractBanyanDBDAO implements IMet
}
}
- @Override
- public List<MetricsValues> readLabeledMetricsValues(MetricsCondition condition, String valueColumnName, List<KeyValue> labels, Duration duration) throws IOException {
+ private List<MetricsValues> invokeReadLabeledMetricsValues(MetricsCondition condition, String valueColumnName, List<KeyValue> labels, Duration duration) throws IOException {
Map<Long, DataPoint> idMap = queryByEntityID(condition, valueColumnName, duration);
List<PointOfTime> tsPoints = duration.assembleDurationPoints();
@@ -219,7 +263,7 @@ public class BanyanDBMetricsQueryDAO extends AbstractBanyanDBDAO implements IMet
TimestampRange timestampRange = new TimestampRange(duration.getStartTimestamp(), duration.getEndTimestamp());
Map<Long, DataPoint> map = new HashMap<>();
- MeasureQueryResponse resp = query(schema, ImmutableSet.of(Metrics.ENTITY_ID), ImmutableSet.of(valueColumnName), timestampRange, new QueryBuilder<MeasureQuery>() {
+ MeasureQueryResponse resp = traceQueryResponse(schema, ImmutableSet.of(Metrics.ENTITY_ID), ImmutableSet.of(valueColumnName), timestampRange, new QueryBuilder<MeasureQuery>() {
@Override
protected void apply(MeasureQuery query) {
query.and(eq(Metrics.ENTITY_ID, entityID));
@@ -235,4 +279,38 @@ public class BanyanDBMetricsQueryDAO extends AbstractBanyanDBDAO implements IMet
return map;
}
+
+ private MeasureQueryResponse traceQueryResponse(MetadataRegistry.Schema schema,
+ Set<String> tags,
+ Set<String> fields,
+ TimestampRange timestampRange,
+ QueryBuilder<MeasureQuery> queryBuilder) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ StringBuilder builder = new StringBuilder();
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query BanyanDB metrics");
+ builder.append("Condition: schema: ")
+ .append(schema)
+ .append(", tags: ")
+ .append(tags)
+ .append(", fields: ")
+ .append(fields)
+ .append(", timestampRange: ")
+ .append(timestampRange);
+ span.setMsg(builder.toString());
+ }
+ MeasureQueryResponse response = query(schema, tags, fields, timestampRange, queryBuilder);
+ if (traceContext != null && traceContext.isDumpStorageRsp()) {
+ builder.append("\n").append(" Response: ").append(new Gson().toJson(response));
+ span.setMsg(builder.toString());
+ }
+ return response;
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
}
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AggregationQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AggregationQueryEsDAO.java
index 6d881829f7..40e48257ab 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AggregationQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AggregationQueryEsDAO.java
@@ -18,7 +18,10 @@
package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query;
+import com.google.gson.Gson;
+import java.util.Arrays;
import java.util.Objects;
+import java.util.function.Supplier;
import org.apache.skywalking.library.elasticsearch.requests.search.BoolQueryBuilder;
import org.apache.skywalking.library.elasticsearch.requests.search.Query;
import org.apache.skywalking.library.elasticsearch.requests.search.RangeQueryBuilder;
@@ -34,6 +37,9 @@ import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
import org.apache.skywalking.oap.server.core.query.type.KeyValue;
import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
@@ -56,6 +62,25 @@ public class AggregationQueryEsDAO extends EsDAO implements IAggregationQueryDAO
final String valueColumnName,
final Duration duration,
final List<KeyValue> additionalConditions) {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Dao: sortMetrics");
+ span.setMsg("TopNCondition: " + condition + ", ValueColumnName: " + valueColumnName + ", Duration: " + duration + ", AdditionalConditions: " + additionalConditions);
+ }
+ return invokeSortMetrics(condition, valueColumnName, duration, additionalConditions);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
+ private List<SelectedRecord> invokeSortMetrics(final TopNCondition condition,
+ final String valueColumnName,
+ final Duration duration,
+ final List<KeyValue> additionalConditions) {
final String realValueColumn = IndexController.LogicIndicesRegister.getPhysicalColumnName(condition.getName(), valueColumnName);
final RangeQueryBuilder basicQuery = Query.range(Metrics.TIME_BUCKET)
.lte(duration.getEndTimeBucket())
@@ -112,7 +137,7 @@ public class AggregationQueryEsDAO extends EsDAO implements IAggregationQueryDAO
.collectMode(TermsAggregationBuilder.CollectMode.BREADTH_FIRST)
.build());
- final SearchResponse response = getClient().search(new TimeRangeIndexNameGenerator(
+ final SearchResponse response = traceSearchResponse(new TimeRangeIndexNameGenerator(
IndexController.LogicIndicesRegister.getPhysicalTableName(condition.getName()),
duration.getStartTimeBucketInSec(),
duration.getEndTimeBucketInSec()), search.build());
@@ -133,4 +158,27 @@ public class AggregationQueryEsDAO extends EsDAO implements IAggregationQueryDAO
}
return topNList;
}
+
+ private SearchResponse traceSearchResponse(Supplier<String[]> indices, Search search) {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ StringBuilder builder = new StringBuilder();
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Elasticsearch");
+ builder.append("Condition: ").append("indices: ").append(Arrays.toString(indices.get()));
+ span.setMsg(builder.toString());
+ }
+ SearchResponse response = getClient().search(indices, search);
+ if (traceContext != null && traceContext.isDumpStorageRsp()) {
+ builder.append("\n").append(" Response: ").append(new Gson().toJson(response));
+ span.setMsg(builder.toString());
+ }
+ return response;
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
}
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetricsQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetricsQueryEsDAO.java
index 48a9e014d7..c33be4c102 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetricsQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetricsQueryEsDAO.java
@@ -18,6 +18,7 @@
package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query;
+import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -44,6 +45,9 @@ import org.apache.skywalking.oap.server.core.query.type.IntValues;
import org.apache.skywalking.oap.server.core.query.type.KVInt;
import org.apache.skywalking.oap.server.core.query.type.KeyValue;
import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
@@ -62,6 +66,46 @@ public class MetricsQueryEsDAO extends EsDAO implements IMetricsQueryDAO {
public MetricsValues readMetricsValues(final MetricsCondition condition,
final String valueColumnName,
final Duration duration) {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Dao: readMetricsValues");
+ span.setMsg(
+ "MetricsCondition: " + condition + ", ValueColumnName: " + valueColumnName + ", Duration: " + duration);
+ }
+ return invokeReadMetricsValues(condition, valueColumnName, duration);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
+ @Override
+ public List<MetricsValues> readLabeledMetricsValues(final MetricsCondition condition,
+ final String valueColumnName,
+ final List<KeyValue> labels,
+ final Duration duration) {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Dao: readLabeledMetricsValues");
+ span.setMsg(
+ "MetricsCondition: " + condition + ", ValueColumnName: " + valueColumnName + ", Labels: " + labels + ", Duration: " + duration);
+ }
+ return invokeReadLabeledMetricsValues(condition, valueColumnName, labels, duration);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
+ private MetricsValues invokeReadMetricsValues(final MetricsCondition condition,
+ final String valueColumnName,
+ final Duration duration) {
final String realValueColumn = IndexController.LogicIndicesRegister.getPhysicalColumnName(condition.getName(), valueColumnName);
String tableName =
IndexController.LogicIndicesRegister.getPhysicalTableName(condition.getName());
@@ -80,7 +124,7 @@ public class MetricsQueryEsDAO extends EsDAO implements IMetricsQueryDAO {
}).collect(Collectors.toList());
MetricsValues metricsValues = new MetricsValues();
- Optional<Documents> response = getClient().ids(indexIdsGroup);
+ Optional<Documents> response = traceQueryResponse(indexIdsGroup);
if (response.isPresent()) {
Map<String, Map<String, Object>> idMap = toMap(response.get());
@@ -109,8 +153,7 @@ public class MetricsQueryEsDAO extends EsDAO implements IMetricsQueryDAO {
return metricsValues;
}
- @Override
- public List<MetricsValues> readLabeledMetricsValues(final MetricsCondition condition,
+ private List<MetricsValues> invokeReadLabeledMetricsValues(final MetricsCondition condition,
final String valueColumnName,
final List<KeyValue> labels,
final Duration duration) {
@@ -133,7 +176,7 @@ public class MetricsQueryEsDAO extends EsDAO implements IMetricsQueryDAO {
indexIdsGroup.computeIfAbsent(indexName, v -> new ArrayList<>()).add(id);
});
- Optional<Documents> response = getClient().ids(indexIdsGroup);
+ Optional<Documents> response = traceQueryResponse(indexIdsGroup);
Map<String, DataTable> idMap = new HashMap<>();
if (response.isPresent()) {
@@ -153,6 +196,29 @@ public class MetricsQueryEsDAO extends EsDAO implements IMetricsQueryDAO {
);
}
+ private Optional<Documents> traceQueryResponse(Map<String, List<String>> indexIdsGroup) {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ StringBuilder builder = new StringBuilder();
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Elasticsearch");
+ builder.append("Condition: ").append("indices: ").append(indexIdsGroup.keySet());
+ span.setMsg(builder.toString());
+ }
+ Optional<Documents> response = getClient().ids(indexIdsGroup);
+ if (traceContext != null && traceContext.isDumpStorageRsp()) {
+ builder.append("\n").append(" Response: ").append(response.isPresent() ? new Gson().toJson(response.get()) : "null");
+ span.setMsg(builder.toString());
+ }
+ return response;
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
public List<MetricsValues> readLabeledMetricsValuesWithoutEntity(final String metricName,
final String valueColumnName,
final List<KeyValue> labels,
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java
index e2e0be0a62..ffd6f23081 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java
@@ -18,6 +18,7 @@
package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query;
+import com.google.gson.Gson;
import org.apache.skywalking.library.elasticsearch.requests.search.BoolQueryBuilder;
import org.apache.skywalking.library.elasticsearch.requests.search.Query;
import org.apache.skywalking.library.elasticsearch.requests.search.Search;
@@ -30,6 +31,9 @@ import org.apache.skywalking.oap.server.core.query.enumeration.Order;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
import org.apache.skywalking.oap.server.core.query.type.Record;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
import org.apache.skywalking.oap.server.library.util.StringUtil;
@@ -48,6 +52,24 @@ public class RecordsQueryEsDAO extends EsDAO implements IRecordsQueryDAO {
@Override
public List<Record> readRecords(final RecordCondition condition,
+ final String valueColumnName,
+ final Duration duration) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Dao: readRecords");
+ span.setMsg("RecordCondition: " + condition + ", ValueColumnName: " + valueColumnName + ", Duration: " + duration);
+ }
+ return invokeReadRecords(condition, valueColumnName, duration);
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
+
+ private List<Record> invokeReadRecords(final RecordCondition condition,
final String valueColumnName,
final Duration duration) throws IOException {
final BoolQueryBuilder query =
@@ -69,7 +91,7 @@ public class RecordsQueryEsDAO extends EsDAO implements IRecordsQueryDAO {
condition.getOrder().equals(Order.DES) ?
Sort.Order.DESC : Sort.Order.ASC
);
- final SearchResponse response = getClient().search(
+ final SearchResponse response = traceSearchResponse(
IndexController.LogicIndicesRegister.getPhysicalTableName(condition.getName()),
search.build()
);
@@ -89,4 +111,27 @@ public class RecordsQueryEsDAO extends EsDAO implements IRecordsQueryDAO {
return results;
}
+
+ private SearchResponse traceSearchResponse(String indexName, Search search) throws IOException {
+ DebuggingTraceContext traceContext = DebuggingTrace.TRACE_CONTEXT.get();
+ DebuggingSpan span = null;
+ try {
+ StringBuilder builder = new StringBuilder();
+ if (traceContext != null) {
+ span = traceContext.createSpan("Query Elasticsearch");
+ builder.append("Condition: ").append("indices: ").append(indexName);
+ span.setMsg(builder.toString());
+ }
+ SearchResponse response = getClient().search(indexName, search);
+ if (traceContext != null && traceContext.isDumpStorageRsp()) {
+ builder.append("\n").append(" Response: ").append(new Gson().toJson(response));
+ span.setMsg(builder.toString());
+ }
+ return response;
+ } finally {
+ if (traceContext != null && span != null) {
+ traceContext.stopSpan(span);
+ }
+ }
+ }
}