You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2020/12/24 04:48:35 UTC
[skywalking] 01/01: test: add e2e for NodeJS agent
This is an automated email from the ASF dual-hosted git repository.
kezhenxu94 pushed a commit to branch e2e/nodejs
in repository https://gitbox.apache.org/repos/asf/skywalking.git
commit 8eb79d94900930ae0aeeedbf466c1eb5bafdb564
Author: kezhenxu94 <ke...@apache.org>
AuthorDate: Thu Dec 24 12:47:59 2020 +0800
test: add e2e for NodeJS agent
---
.github/workflows/e2e.nodejs.yaml | 53 ++++
.../apache/skywalking/e2e/topo/TopoMatcher.java | 6 +-
test/e2e/e2e-test/docker/nodejs/Dockerfile.nodejs | 30 +++
test/e2e/e2e-test/docker/nodejs/consumer.ts | 40 +++
test/e2e/e2e-test/docker/nodejs/docker-compose.yml | 94 +++++++
test/e2e/e2e-test/docker/nodejs/provider.ts | 35 +++
.../java/org/apache/skywalking/e2e/NodeJSE2E.java | 288 +++++++++++++++++++++
.../expected/nodejs/consumer-endpoints.yml | 18 ++
.../expected/nodejs/consumer-instance-topo.yml | 33 +++
.../expected/nodejs/consumer-instances.yml | 18 ++
.../expected/nodejs/provider-endpoints.yml | 18 ++
.../expected/nodejs/provider-instances.yml | 18 ++
.../test/resources/expected/nodejs/services.yml | 22 ++
.../src/test/resources/expected/nodejs/topo.yml | 50 ++++
.../src/test/resources/expected/nodejs/traces.yml | 24 ++
15 files changed, 745 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/e2e.nodejs.yaml b/.github/workflows/e2e.nodejs.yaml
new file mode 100644
index 0000000..ca859b5
--- /dev/null
+++ b/.github/workflows/e2e.nodejs.yaml
@@ -0,0 +1,53 @@
+# 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.
+
+name: E2E-NodeJS
+
+on:
+ pull_request:
+ paths:
+ - '**'
+ - '!**.md'
+ push:
+ branches:
+ - master
+
+env:
+ SKIP_TEST: true
+ SW_AGENT_JDK_VERSION: 8
+
+jobs:
+ NodeJSAgent:
+ name: NodeJSAgent
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: true
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+ - name: Compile and Build
+ run: make docker
+ - name: Copy dist package
+ run: cp -R dist test/e2e/
+ - name: NodeJS Agent
+ run: ./mvnw --batch-mode -f test/e2e/pom.xml -am -DfailIfNoTests=false verify -Dit.test=org.apache.skywalking.e2e.NodeJSE2E
diff --git a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/topo/TopoMatcher.java b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/topo/TopoMatcher.java
index 68fa411..dc6ab3d 100644
--- a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/topo/TopoMatcher.java
+++ b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/topo/TopoMatcher.java
@@ -55,7 +55,8 @@ public class TopoMatcher extends AbstractMatcher<Topology> {
try {
getNodes().get(i).verify(topology.getNodes().get(j));
matched = true;
- } catch (Throwable ignored) {
+ } catch (Throwable e) {
+ e.printStackTrace();
}
}
if (!matched) {
@@ -71,7 +72,8 @@ public class TopoMatcher extends AbstractMatcher<Topology> {
try {
getCalls().get(i).verify(topology.getCalls().get(j));
matched = true;
- } catch (Throwable ignored) {
+ } catch (Throwable e) {
+ e.printStackTrace();
}
}
if (!matched) {
diff --git a/test/e2e/e2e-test/docker/nodejs/Dockerfile.nodejs b/test/e2e/e2e-test/docker/nodejs/Dockerfile.nodejs
new file mode 100644
index 0000000..5cb1f4e
--- /dev/null
+++ b/test/e2e/e2e-test/docker/nodejs/Dockerfile.nodejs
@@ -0,0 +1,30 @@
+# 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.
+
+FROM node:12
+
+ENV COMMIT_HASH=55daa7e6385b6236987a5e26bb39242724730455
+
+WORKDIR /app
+
+EXPOSE 5050 5051
+
+RUN git clone https://github.com/apache/skywalking-nodejs.git $(pwd)
+
+RUN git reset --hard ${COMMIT_HASH} && git submodule update --init
+
+RUN npm install
+RUN npm run generate-source
+RUN npm install express axios
diff --git a/test/e2e/e2e-test/docker/nodejs/consumer.ts b/test/e2e/e2e-test/docker/nodejs/consumer.ts
new file mode 100644
index 0000000..f5405e0
--- /dev/null
+++ b/test/e2e/e2e-test/docker/nodejs/consumer.ts
@@ -0,0 +1,40 @@
+/*!
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import * as http from 'http';
+import agent from './src';
+import axios from 'axios';
+
+agent.start({
+ serviceName: 'consumer',
+ maxBufferSize: 1000,
+});
+
+const server = http.createServer((req, res) => {
+ axios
+ .post(`http://${process.env.SERVER || 'localhost:5000'}${req.url}`, {}, {
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+ .then((r) => res.end(JSON.stringify(r.data)))
+ .catch(err => res.end(JSON.stringify(err.message)));
+});
+
+server.listen(5001, () => console.info('Listening on port 5001...'));
diff --git a/test/e2e/e2e-test/docker/nodejs/docker-compose.yml b/test/e2e/e2e-test/docker/nodejs/docker-compose.yml
new file mode 100644
index 0000000..aa45c8d
--- /dev/null
+++ b/test/e2e/e2e-test/docker/nodejs/docker-compose.yml
@@ -0,0 +1,94 @@
+# 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.
+
+version: '2.1'
+
+services:
+ oap:
+ extends:
+ file: ../base-compose.yml
+ service: oap
+
+ ui:
+ extends:
+ file: ../base-compose.yml
+ service: ui
+ depends_on:
+ oap:
+ condition: service_healthy
+
+ provider:
+ build:
+ context: .
+ dockerfile: Dockerfile.nodejs
+ networks:
+ - e2e
+ expose:
+ - 5000
+ environment:
+ SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
+ SW_AGENT_INSTANCE: provider-instance
+ volumes:
+ - ./provider.ts:/app/provider.ts
+ depends_on:
+ oap:
+ condition: service_healthy
+ healthcheck:
+ test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/5000" ]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+ entrypoint: [ 'npx', 'ts-node', '/app/provider.ts' ]
+
+ medium:
+ extends:
+ file: ../base-compose.yml
+ service: consumer
+ environment:
+ PROVIDER_URL: http://provider:5000
+ depends_on:
+ oap:
+ condition: service_healthy
+ provider:
+ condition: service_healthy
+
+ consumer:
+ build:
+ context: .
+ dockerfile: Dockerfile.nodejs
+ networks:
+ - e2e
+ expose:
+ - 5001
+ environment:
+ SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
+ SW_AGENT_INSTANCE: consumer-instance
+ SERVER: medium:9092
+ volumes:
+ - ./consumer.ts:/app/consumer.ts
+ depends_on:
+ oap:
+ condition: service_healthy
+ medium:
+ condition: service_healthy
+ healthcheck:
+ test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/5051" ]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+ entrypoint: [ 'npx', 'ts-node', '/app/consumer.ts' ]
+
+networks:
+ e2e:
diff --git a/test/e2e/e2e-test/docker/nodejs/provider.ts b/test/e2e/e2e-test/docker/nodejs/provider.ts
new file mode 100644
index 0000000..97410c8
--- /dev/null
+++ b/test/e2e/e2e-test/docker/nodejs/provider.ts
@@ -0,0 +1,35 @@
+/*!
+ *
+ * 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.
+ *
+ */
+
+import agent from './src';
+
+import express from 'express';
+
+agent.start({
+ serviceName: 'provider',
+ maxBufferSize: 1000,
+});
+const app = express();
+
+const handle = (req, res) => setTimeout(() => res.send({'id': 1, 'name': 'ke'}), 200);
+
+app.get('/users', handle);
+app.post('/users', handle);
+
+app.listen(5000, () => console.info('Listening on port 5000...'));
diff --git a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/NodeJSE2E.java b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/NodeJSE2E.java
new file mode 100644
index 0000000..73133c8
--- /dev/null
+++ b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/NodeJSE2E.java
@@ -0,0 +1,288 @@
+/*
+ * 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.e2e;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.e2e.annotation.ContainerHostAndPort;
+import org.apache.skywalking.e2e.annotation.DockerCompose;
+import org.apache.skywalking.e2e.base.SkyWalkingE2E;
+import org.apache.skywalking.e2e.base.SkyWalkingTestAdapter;
+import org.apache.skywalking.e2e.common.HostAndPort;
+import org.apache.skywalking.e2e.metrics.AtLeastOneOfMetricsMatcher;
+import org.apache.skywalking.e2e.metrics.Metrics;
+import org.apache.skywalking.e2e.metrics.MetricsQuery;
+import org.apache.skywalking.e2e.metrics.MetricsValueMatcher;
+import org.apache.skywalking.e2e.retryable.RetryableTest;
+import org.apache.skywalking.e2e.service.Service;
+import org.apache.skywalking.e2e.service.ServicesMatcher;
+import org.apache.skywalking.e2e.service.ServicesQuery;
+import org.apache.skywalking.e2e.service.endpoint.Endpoint;
+import org.apache.skywalking.e2e.service.endpoint.EndpointQuery;
+import org.apache.skywalking.e2e.service.endpoint.Endpoints;
+import org.apache.skywalking.e2e.service.endpoint.EndpointsMatcher;
+import org.apache.skywalking.e2e.service.instance.Instance;
+import org.apache.skywalking.e2e.service.instance.Instances;
+import org.apache.skywalking.e2e.service.instance.InstancesMatcher;
+import org.apache.skywalking.e2e.service.instance.InstancesQuery;
+import org.apache.skywalking.e2e.topo.Call;
+import org.apache.skywalking.e2e.topo.ServiceInstanceTopology;
+import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyMatcher;
+import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyQuery;
+import org.apache.skywalking.e2e.topo.TopoMatcher;
+import org.apache.skywalking.e2e.topo.TopoQuery;
+import org.apache.skywalking.e2e.topo.Topology;
+import org.apache.skywalking.e2e.trace.Trace;
+import org.apache.skywalking.e2e.trace.TracesMatcher;
+import org.apache.skywalking.e2e.trace.TracesQuery;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.testcontainers.containers.DockerComposeContainer;
+
+import static org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyMetrics;
+import static org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyPercentileMetrics;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_ENDPOINT_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_ENDPOINT_MULTIPLE_LINEAR_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_INSTANCE_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_MULTIPLE_LINEAR_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_CLIENT_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_SERVER_METRICS;
+import static org.apache.skywalking.e2e.utils.Times.now;
+import static org.apache.skywalking.e2e.utils.Yamls.load;
+
+@Slf4j
+@SkyWalkingE2E
+public class NodeJSE2E extends SkyWalkingTestAdapter {
+ @SuppressWarnings("unused")
+ @DockerCompose("docker/nodejs/docker-compose.yml")
+ private DockerComposeContainer<?> justForSideEffects;
+
+ @SuppressWarnings("unused")
+ @ContainerHostAndPort(name = "ui", port = 8080)
+ private HostAndPort swWebappHostPort;
+
+ @SuppressWarnings("unused")
+ @ContainerHostAndPort(name = "consumer", port = 5001)
+ private HostAndPort nodejsHostPort;
+
+ @BeforeAll
+ public void setUp() throws Exception {
+ queryClient(swWebappHostPort);
+
+ trafficController(nodejsHostPort, "/users");
+ }
+
+ @AfterAll
+ public void tearDown() {
+ trafficController.stop();
+ }
+
+ @RetryableTest
+ void services() throws Exception {
+ List<Service> services = graphql.services(new ServicesQuery().start(startTime).end(now()));
+ services = services.stream().filter(s -> !s.getLabel().equals("oap::oap-server")).collect(Collectors.toList());
+ LOGGER.info("services: {}", services);
+
+ load("expected/nodejs/services.yml").as(ServicesMatcher.class).verify(services);
+
+ for (Service service : services) {
+ if ("Your_ApplicationName".equals(service.getLabel())) {
+ continue;
+ }
+
+ LOGGER.info("verifying service instances: {}", service);
+
+ verifyServiceMetrics(service);
+
+ final Instances instances = verifyServiceInstances(service);
+
+ verifyInstancesMetrics(instances);
+
+ final Endpoints endpoints = verifyServiceEndpoints(service);
+
+ verifyEndpointsMetrics(endpoints);
+ }
+ }
+
+ @RetryableTest
+ void traces() throws Exception {
+ final List<Trace> traces = graphql.traces(new TracesQuery().start(startTime).end(now()).orderByStartTime());
+
+ LOGGER.info("traces: {}", traces);
+
+ load("expected/nodejs/traces.yml").as(TracesMatcher.class).verifyLoosely(traces);
+ }
+
+ @RetryableTest
+ void topology() throws Exception {
+ final Topology topology = graphql.topo(new TopoQuery().stepByMinute().start(startTime.minusDays(1)).end(now()));
+
+ LOGGER.info("topology: {}", topology);
+
+ load("expected/nodejs/topo.yml").as(TopoMatcher.class).verify(topology);
+
+ verifyServiceRelationMetrics(topology.getCalls());
+ }
+
+ @RetryableTest
+ void serviceInstances() throws Exception {
+
+ final ServiceInstanceTopology topology = graphql.serviceInstanceTopo(
+ new ServiceInstanceTopologyQuery().stepByMinute()
+ .start(startTime.minusDays(1))
+ .end(now())
+ .clientServiceId("Y29uc3VtZXI=.1")
+ .serverServiceId("WW91cl9BcHBsaWNhdGlvbk5hbWU=.1"));
+
+ LOGGER.info("topology: {}", topology);
+
+ load("expected/nodejs/consumer-instance-topo.yml").as(ServiceInstanceTopologyMatcher.class).verify(topology);
+
+ verifyServiceInstanceRelationMetrics(topology.getCalls());
+ }
+
+ private Instances verifyServiceInstances(final Service service) throws Exception {
+ final Instances instances = graphql.instances(
+ new InstancesQuery().serviceId(service.getKey()).start(startTime).end(now())
+ );
+
+ LOGGER.info("instances: {} {}", service.getLabel(), instances);
+
+ load(String.format("expected/nodejs/%s-instances.yml", service.getLabel()))
+ .as(InstancesMatcher.class)
+ .verify(instances);
+
+ return instances;
+ }
+
+ private Endpoints verifyServiceEndpoints(final Service service) throws Exception {
+ final Endpoints endpoints = graphql.endpoints(new EndpointQuery().serviceId(service.getKey()));
+
+ LOGGER.info("endpoints: {} {}", service.getLabel(), endpoints);
+
+ load(String.format("expected/nodejs/%s-endpoints.yml", service.getLabel()))
+ .as(EndpointsMatcher.class)
+ .verify(endpoints);
+
+ return endpoints;
+ }
+
+ private void verifyInstancesMetrics(Instances instances) throws Exception {
+ for (Instance instance : instances.getInstances()) {
+ for (String metricsName : ALL_INSTANCE_METRICS) {
+ LOGGER.info("verifying service instance response time: {}", instance);
+ final Metrics instanceMetrics = graphql.metrics(
+ new MetricsQuery().stepByMinute().metricsName(metricsName).id(instance.getKey())
+ );
+
+ LOGGER.info("instance metrics: {}", instanceMetrics);
+
+ final AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
+ final MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
+ greaterThanZero.setValue("gt 0");
+ instanceRespTimeMatcher.setValue(greaterThanZero);
+ instanceRespTimeMatcher.verify(instanceMetrics);
+ LOGGER.info("{}: {}", metricsName, instanceMetrics);
+ }
+ }
+ }
+
+ private void verifyEndpointsMetrics(Endpoints endpoints) throws Exception {
+ for (Endpoint endpoint : endpoints.getEndpoints()) {
+ for (final String metricName : ALL_ENDPOINT_METRICS) {
+ LOGGER.info("verifying endpoint {}: {}", endpoint, metricName);
+
+ final Metrics metrics = graphql.metrics(
+ new MetricsQuery().stepByMinute().metricsName(metricName).id(endpoint.getKey())
+ );
+
+ LOGGER.info("metrics: {}", metrics);
+
+ final AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
+ final MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
+ greaterThanZero.setValue("gt 0");
+ instanceRespTimeMatcher.setValue(greaterThanZero);
+ instanceRespTimeMatcher.verify(metrics);
+
+ LOGGER.info("{}: {}", metricName, metrics);
+ }
+ for (String metricName : ALL_ENDPOINT_MULTIPLE_LINEAR_METRICS) {
+ verifyPercentileMetrics(graphql, metricName, endpoint.getKey(), startTime);
+ }
+ }
+ }
+
+ private void verifyServiceMetrics(final Service service) throws Exception {
+ for (String metricName : ALL_SERVICE_METRICS) {
+ LOGGER.info("verifying service {}, metrics: {}", service, metricName);
+ final Metrics serviceMetrics = graphql.metrics(
+ new MetricsQuery().stepByMinute().metricsName(metricName).id(service.getKey())
+ );
+ LOGGER.info("serviceMetrics: {}", serviceMetrics);
+ final AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
+ final MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
+ greaterThanZero.setValue("gt 0");
+ instanceRespTimeMatcher.setValue(greaterThanZero);
+ instanceRespTimeMatcher.verify(serviceMetrics);
+ LOGGER.info("{}: {}", metricName, serviceMetrics);
+ }
+
+ for (String metricName : ALL_SERVICE_MULTIPLE_LINEAR_METRICS) {
+ verifyPercentileMetrics(graphql, metricName, service.getKey(), startTime);
+ }
+ }
+
+ private void verifyServiceInstanceRelationMetrics(final List<Call> calls) throws Exception {
+ verifyRelationMetrics(
+ calls, ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS,
+ ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS
+ );
+ }
+
+ private void verifyServiceRelationMetrics(final List<Call> calls) throws Exception {
+ verifyRelationMetrics(calls, ALL_SERVICE_RELATION_CLIENT_METRICS, ALL_SERVICE_RELATION_SERVER_METRICS);
+ }
+
+ private void verifyRelationMetrics(final List<Call> calls,
+ final String[] relationClientMetrics,
+ final String[] relationServerMetrics) throws Exception {
+ for (Call call : calls) {
+ for (String detectPoint : call.getDetectPoints()) {
+ switch (detectPoint) {
+ case "CLIENT": {
+ for (String metricName : relationClientMetrics) {
+ verifyMetrics(graphql, metricName, call.getId(), startTime);
+ }
+ break;
+ }
+ case "SERVER": {
+ for (String metricName : relationServerMetrics) {
+ verifyMetrics(graphql, metricName, call.getId(), startTime);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/test/e2e/e2e-test/src/test/resources/expected/nodejs/consumer-endpoints.yml b/test/e2e/e2e-test/src/test/resources/expected/nodejs/consumer-endpoints.yml
new file mode 100644
index 0000000..9a5a477
--- /dev/null
+++ b/test/e2e/e2e-test/src/test/resources/expected/nodejs/consumer-endpoints.yml
@@ -0,0 +1,18 @@
+# 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.
+
+endpoints:
+ - key: not null
+ label: /users
diff --git a/test/e2e/e2e-test/src/test/resources/expected/nodejs/consumer-instance-topo.yml b/test/e2e/e2e-test/src/test/resources/expected/nodejs/consumer-instance-topo.yml
new file mode 100644
index 0000000..c51177d
--- /dev/null
+++ b/test/e2e/e2e-test/src/test/resources/expected/nodejs/consumer-instance-topo.yml
@@ -0,0 +1,33 @@
+# 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.
+
+nodes:
+ - id: not null
+ name: consumer-instance
+ serviceId: not null
+ serviceName: consumer
+ isReal: true
+ - id: not null
+ name: not null
+ serviceId: not null
+ serviceName: Your_ApplicationName
+ isReal: true
+calls:
+ - id: not null
+ source: Y29uc3VtZXI=.1_Y29uc3VtZXItaW5zdGFuY2U=
+ detectPoints:
+ - CLIENT
+ - SERVER
+ target: not null
diff --git a/test/e2e/e2e-test/src/test/resources/expected/nodejs/consumer-instances.yml b/test/e2e/e2e-test/src/test/resources/expected/nodejs/consumer-instances.yml
new file mode 100644
index 0000000..7de572a
--- /dev/null
+++ b/test/e2e/e2e-test/src/test/resources/expected/nodejs/consumer-instances.yml
@@ -0,0 +1,18 @@
+# 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.
+
+instances:
+ - key: not null
+ label: not null
diff --git a/test/e2e/e2e-test/src/test/resources/expected/nodejs/provider-endpoints.yml b/test/e2e/e2e-test/src/test/resources/expected/nodejs/provider-endpoints.yml
new file mode 100644
index 0000000..9a5a477
--- /dev/null
+++ b/test/e2e/e2e-test/src/test/resources/expected/nodejs/provider-endpoints.yml
@@ -0,0 +1,18 @@
+# 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.
+
+endpoints:
+ - key: not null
+ label: /users
diff --git a/test/e2e/e2e-test/src/test/resources/expected/nodejs/provider-instances.yml b/test/e2e/e2e-test/src/test/resources/expected/nodejs/provider-instances.yml
new file mode 100644
index 0000000..7de572a
--- /dev/null
+++ b/test/e2e/e2e-test/src/test/resources/expected/nodejs/provider-instances.yml
@@ -0,0 +1,18 @@
+# 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.
+
+instances:
+ - key: not null
+ label: not null
diff --git a/test/e2e/e2e-test/src/test/resources/expected/nodejs/services.yml b/test/e2e/e2e-test/src/test/resources/expected/nodejs/services.yml
new file mode 100644
index 0000000..5aea577
--- /dev/null
+++ b/test/e2e/e2e-test/src/test/resources/expected/nodejs/services.yml
@@ -0,0 +1,22 @@
+# 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.
+
+services:
+ - key: not null
+ label: provider
+ - key: not null
+ label: consumer
+ - key: not null
+ label: Your_ApplicationName
diff --git a/test/e2e/e2e-test/src/test/resources/expected/nodejs/topo.yml b/test/e2e/e2e-test/src/test/resources/expected/nodejs/topo.yml
new file mode 100644
index 0000000..f8fd438
--- /dev/null
+++ b/test/e2e/e2e-test/src/test/resources/expected/nodejs/topo.yml
@@ -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.
+
+nodes:
+ - id: not null
+ name: User
+ type: USER
+ isReal: false
+ - id: not null
+ name: consumer
+ type: http
+ isReal: true
+ - id: not null
+ name: provider
+ type: Express
+ isReal: true
+ - id: not null
+ name: Your_ApplicationName
+ type: Tomcat
+ isReal: true
+calls:
+ - id: not null
+ source: ${User[0]}
+ detectPoints:
+ - SERVER
+ target: ${consumer[0]}
+ - id: not null
+ source: ${consumer[0]}
+ detectPoints:
+ - CLIENT
+ - SERVER
+ target: ${Your_ApplicationName[0]}
+ - id: not null
+ source: ${Your_ApplicationName[0]}
+ detectPoints:
+ - CLIENT
+ - SERVER
+ target: ${provider[0]}
diff --git a/test/e2e/e2e-test/src/test/resources/expected/nodejs/traces.yml b/test/e2e/e2e-test/src/test/resources/expected/nodejs/traces.yml
new file mode 100644
index 0000000..8d5f8cc
--- /dev/null
+++ b/test/e2e/e2e-test/src/test/resources/expected/nodejs/traces.yml
@@ -0,0 +1,24 @@
+# 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.
+
+traces:
+ - key: not null
+ endpointNames:
+ - /users
+ duration: ge 0
+ start: gt 0
+ isError: false
+ traceIds:
+ - not null