diff --git a/Jenkinsfile b/Jenkinsfile
index 102ec4f8c2cfbd114f60a8dd073ff781dfd170f6..86d4fa286cb6daa87f3ebf79c95c9badddf9f65c 100755
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -27,6 +27,10 @@ pipeline {
skipStagesAfterUnstable()
}
+ environment {
+ MAVEN_OPTS = '-Dmaven.repo.local=.m2/repository -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:-UseGCOverheadLimit -Xmx3g'
+ }
+
stages {
stage('Install & Test') {
parallel {
diff --git a/Jenkinsfile-E2E b/Jenkinsfile-E2E
index c2ec97b94b4ae3e4ff3778720143a66cac053026..9546fd93fd9d7b8c6aa5b1dfaad75082ec7a0858 100755
--- a/Jenkinsfile-E2E
+++ b/Jenkinsfile-E2E
@@ -26,7 +26,7 @@ pipeline {
}
environment {
- MAVEN_OPTS = '-XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:-UseGCOverheadLimit -Xmx3g'
+ MAVEN_OPTS = '-Dmaven.repo.local=.m2/repository -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:-UseGCOverheadLimit -Xmx3g'
}
stages {
@@ -55,7 +55,7 @@ pipeline {
stage('Compile Test Codes') {
steps {
- sh './mvnw -f test/e2e/pom.xml clean'
+ sh './mvnw -f test/e2e/pom.xml -pl e2e-base clean install'
}
}
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLoggerTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLoggerTest.java
index f940b091265cc59f66d04937f6ea8f3b9ff4dfc0..842de0588c0f561f7f38684232a8f616c3c7b5b6 100644
--- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLoggerTest.java
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLoggerTest.java
@@ -23,13 +23,11 @@ import com.google.common.collect.Lists;
import org.apache.skywalking.apm.agent.core.conf.Config;
import org.apache.skywalking.apm.agent.core.conf.Constants;
import org.hamcrest.core.StringContains;
-import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
-import java.io.PrintStream;
import java.util.List;
import static org.mockito.Matchers.anyString;
@@ -42,28 +40,20 @@ public class PatternLoggerTest {
public static final String PATTERN = "%timestamp+0800 %level [%agent_name,,,] [%thread] %class:-1 %msg %throwable";
- private static PrintStream OUT_REF;
- private static PrintStream ERR_REF;
-
@BeforeClass
public static void initAndHoldOut() {
- OUT_REF = System.out;
- ERR_REF = System.err;
Config.Agent.SERVICE_NAME = "testAppFromConfig";
}
@Test
public void testLog() {
- PrintStream output = Mockito.mock(PrintStream.class);
- System.setOut(output);
- PrintStream err = Mockito.mock(PrintStream.class);
- System.setErr(err);
+ final IWriter output = Mockito.mock(IWriter.class);
PatternLogger logger = new PatternLogger(PatternLoggerTest.class, PATTERN) {
@Override
protected void logger(LogLevel level, String message, Throwable e) {
String r = format(level, message, e);
- SystemOutWriter.INSTANCE.write(r);
+ output.write(r);
}
};
@@ -84,19 +74,16 @@ public class PatternLoggerTest {
logger.error(new NullPointerException(), "hello {}", "world");
Mockito.verify(output, times(9))
- .println(anyString());
+ .write(anyString());
}
@Test
public void testLogWithSpecialChar() {
- PrintStream output = Mockito.mock(PrintStream.class);
- System.setOut(output);
- PrintStream err = Mockito.mock(PrintStream.class);
- System.setErr(err);
+ final IWriter output = Mockito.mock(IWriter.class);
PatternLogger logger = new PatternLogger(PatternLoggerTest.class, PATTERN) {
@Override
protected void logger(LogLevel level, String message, Throwable e) {
- SystemOutWriter.INSTANCE.write(format(level, message, e));
+ output.write(format(level, message, e));
}
};
@@ -117,7 +104,7 @@ public class PatternLoggerTest {
logger.error(new NullPointerException(), "hello {}", "&&&**%%");
Mockito.verify(output, times(9))
- .println(anyString());
+ .write(anyString());
}
@Test
@@ -156,10 +143,4 @@ public class PatternLoggerTest {
}
- @AfterClass
- public static void reset() {
- System.setOut(OUT_REF);
- System.setErr(ERR_REF);
- }
-
}
diff --git a/docs/en/setup/backend/backend-setup.md b/docs/en/setup/backend/backend-setup.md
index 335d5c45edea63038aa187821140fb91254e684c..9555fd1f01b9fae04408d2b5deb048e21f94f06d 100755
--- a/docs/en/setup/backend/backend-setup.md
+++ b/docs/en/setup/backend/backend-setup.md
@@ -83,6 +83,8 @@ system.
set the expired time for each dimension.
1. [Dynamic Configuration](dynamic-config.md). Make configuration of OAP changed dynamic, from remote service
or 3rd party configuration management system.
+1. [Uninstrumented Gateways](uninstrumented-gateways.md). Configure gateways/proxies that are not supported by SkyWalking agent plugins,
+to reflect the delegation in topology graph.
## Telemetry for backend
OAP backend cluster itself underlying is a distributed streaming process system. For helping the Ops team,
@@ -112,4 +114,4 @@ For example, metrics time will be formatted like YYYYMMDDHHmm in minute dimensio
which format process is timezone related.
In default, SkyWalking OAP backend choose the OS default timezone.
-If you want to override it, please follow Java and OS documents to do so.
\ No newline at end of file
+If you want to override it, please follow Java and OS documents to do so.
diff --git a/docs/en/setup/backend/dynamic-config.md b/docs/en/setup/backend/dynamic-config.md
old mode 100644
new mode 100755
index 9aadb7cb8a62d1d8967476f9fd32c3cc0c71b407..fc9372b305ce389c98d5086daa1e7d377561ccd9
--- a/docs/en/setup/backend/dynamic-config.md
+++ b/docs/en/setup/backend/dynamic-config.md
@@ -7,6 +7,7 @@ Right now, SkyWalking supports following dynamic configurations.
| Config Key | Value Description | Value Format Example |
|:----:|:----:|:----:|
|receiver-trace.default.slowDBAccessThreshold| Thresholds of slow Database statement, override `receiver-trace/default/slowDBAccessThreshold` of `applciation.yml`. | default:200,mongodb:50|
+|receiver-trace.default.uninstrumentedGateways| The uninstrumented gateways, override `gateways.yml`. | not set |
This feature depends on upstream service, so it is **OFF** as default.
diff --git a/docs/en/setup/backend/uninstrumented-gateways.md b/docs/en/setup/backend/uninstrumented-gateways.md
new file mode 100755
index 0000000000000000000000000000000000000000..b1be04cbc087809d0085490d79fa556391b83781
--- /dev/null
+++ b/docs/en/setup/backend/uninstrumented-gateways.md
@@ -0,0 +1,22 @@
+# Uninstrumented Gateways/Proxies
+
+The uninstrumented gateways are not instrumented by SkyWalking agent plugin when they are started,
+but they can be configured in `gateways.yml` file or via [Dynamic Configuration](dynamic-config.md). The reason why they can't register
+to backend automatically is that there're no suitable agent plugins, for example, there is no agent plugins for Nginx, haproxy, etc.
+So in order to visualize the real topology, we provide a way to configure the gateways/proxies manually.
+
+## Configuration Format
+
+The configuration content includes the gateways' names and their instances:
+
+```yml
+gateways:
+ - name: proxy0 # the name is not used for now
+ instances:
+ - host: 127.0.0.1 # the host/ip of this gateway instance
+ port: 9099 # the port of this gateway instance, defaults to 80
+```
+
+**Note** that the `host` of the instance must be the one that is actually used in client side, for example,
+if the instance `proxyA` has 2 IPs, say `192.168.1.110` and `192.168.1.111`, both of which delegates the target service,
+and the client connects to `192.168.1.110`, then configuring `192.168.1.111` as the `host` won't work properly.
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/ServiceInventory.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/ServiceInventory.java
index 5441cc137a90a73ab0c4a8fe6d0f49485ea68616..af910a3dad573a1c0eb143505f2e6afddb6b98d2 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/ServiceInventory.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/ServiceInventory.java
@@ -58,6 +58,8 @@ public class ServiceInventory extends RegisterSource {
@Getter(AccessLevel.PRIVATE) @Column(columnName = PROPERTIES) private String prop = Const.EMPTY_JSON_OBJECT_STRING;
@Getter private JsonObject properties;
+ @Getter @Setter private boolean resetServiceMapping = false;
+
public NodeType getServiceNodeType() {
return NodeType.get(this.nodeType);
}
@@ -119,6 +121,7 @@ public class ServiceInventory extends RegisterSource {
inventory.setAddressId(addressId);
inventory.setLastUpdateTime(getLastUpdateTime());
inventory.setMappingServiceId(mappingServiceId);
+ inventory.setResetServiceMapping(resetServiceMapping);
inventory.setProp(prop);
return inventory;
@@ -150,6 +153,7 @@ public class ServiceInventory extends RegisterSource {
remoteBuilder.addDataIntegers(addressId);
remoteBuilder.addDataIntegers(mappingServiceId);
remoteBuilder.addDataIntegers(nodeType);
+ remoteBuilder.addDataIntegers(resetServiceMapping ? 1 : 0);
remoteBuilder.addDataLongs(getRegisterTime());
remoteBuilder.addDataLongs(getHeartbeatTime());
@@ -166,6 +170,7 @@ public class ServiceInventory extends RegisterSource {
setAddressId(remoteData.getDataIntegers(2));
setMappingServiceId(remoteData.getDataIntegers(3));
setNodeType(remoteData.getDataIntegers(4));
+ setResetServiceMapping(remoteData.getDataIntegers(5) == 1);
setRegisterTime(remoteData.getDataLongs(0));
setHeartbeatTime(remoteData.getDataLongs(1));
@@ -186,8 +191,11 @@ public class ServiceInventory extends RegisterSource {
if (serviceInventory.getLastUpdateTime() >= this.getLastUpdateTime()) {
this.nodeType = serviceInventory.getNodeType();
+ this.resetServiceMapping = serviceInventory.isResetServiceMapping();
setProp(serviceInventory.getProp());
- if (Const.NONE != serviceInventory.getMappingServiceId()) {
+ if (serviceInventory.isResetServiceMapping()) {
+ this.mappingServiceId = Const.NONE;
+ } else if (Const.NONE != serviceInventory.getMappingServiceId()) {
this.mappingServiceId = serviceInventory.getMappingServiceId();
}
isChanged = true;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/service/IServiceInventoryRegister.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/service/IServiceInventoryRegister.java
old mode 100644
new mode 100755
index 93fdc25debc4b3d0c111ee38ca15b955312d9159..3aba70732ca24da741b2be0553d23db2a0a8a831
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/service/IServiceInventoryRegister.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/service/IServiceInventoryRegister.java
@@ -36,4 +36,16 @@ public interface IServiceInventoryRegister extends Service {
void heartbeat(int serviceId, long heartBeatTime);
void updateMapping(int serviceId, int mappingServiceId);
+
+ /**
+ * Reset the {@link org.apache.skywalking.oap.server.core.register.ServiceInventory#mappingServiceId}
+ * of a given service id.
+ *
+ * There are cases when the mapping service id needs to be reset to {@code 0}, for example, when an
+ * uninstrumented gateway joins, the mapping service id of the services that are delegated by this gateway
+ * should be reset to {@code 0}, allowing the gateway to appear in the topology, see #3308 for more detail.
+ *
+ * @param serviceId id of the service whose mapping service id is to be reset
+ */
+ void resetMapping(int serviceId);
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/service/ServiceInventoryRegister.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/service/ServiceInventoryRegister.java
index b5640b37d9eee2c2ac2a6a97c64dce224a862b75..8b276b23ba14759fead4340f58263994b5329399 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/service/ServiceInventoryRegister.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/register/service/ServiceInventoryRegister.java
@@ -19,14 +19,18 @@
package org.apache.skywalking.oap.server.core.register.service;
import com.google.gson.JsonObject;
-import java.util.Objects;
-import org.apache.skywalking.oap.server.core.*;
+import org.apache.skywalking.oap.server.core.Const;
+import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.cache.ServiceInventoryCache;
-import org.apache.skywalking.oap.server.core.register.*;
+import org.apache.skywalking.oap.server.core.register.NodeType;
+import org.apache.skywalking.oap.server.core.register.ServiceInventory;
import org.apache.skywalking.oap.server.core.register.worker.InventoryStreamProcessor;
import org.apache.skywalking.oap.server.library.module.ModuleDefineHolder;
import org.apache.skywalking.oap.server.library.util.BooleanUtils;
-import org.slf4j.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Objects;
import static java.util.Objects.isNull;
@@ -132,6 +136,19 @@ public class ServiceInventoryRegister implements IServiceInventoryRegister {
}
}
+ @Override public void resetMapping(int serviceId) {
+ ServiceInventory serviceInventory = getServiceInventoryCache().get(serviceId);
+ if (Objects.nonNull(serviceInventory)) {
+ serviceInventory = serviceInventory.getClone();
+ serviceInventory.setLastUpdateTime(System.currentTimeMillis());
+ serviceInventory.setResetServiceMapping(true);
+
+ InventoryStreamProcessor.getInstance().in(serviceInventory);
+ } else {
+ logger.warn("Service {} mapping update, but not found in storage.", serviceId);
+ }
+ }
+
private boolean compare(ServiceInventory newServiceInventory, NodeType nodeType) {
if (Objects.nonNull(newServiceInventory)) {
return nodeType.equals(newServiceInventory.getServiceNodeType());
diff --git a/oap-server/server-library/library-client/pom.xml b/oap-server/server-library/library-client/pom.xml
old mode 100644
new mode 100755
index 28f019c9b83edf892c7a920439fafe8ddc7ceb16..faf65d09c7162c32648acaa279f9d51a728992ab
--- a/oap-server/server-library/library-client/pom.xml
+++ b/oap-server/server-library/library-client/pom.xml
@@ -87,7 +87,7 @@
started
-
+
single-node
diff --git a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/TraceModuleProvider.java b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/TraceModuleProvider.java
old mode 100644
new mode 100755
index a1502e3d9f99e4b9f883ad55def4ac5f6ac361d5..3890f9e00e246508e5b2707dc1a4ff9c1e94c5bd
--- a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/TraceModuleProvider.java
+++ b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/TraceModuleProvider.java
@@ -18,23 +18,34 @@
package org.apache.skywalking.oap.server.receiver.trace.provider;
-import java.io.IOException;
-import org.apache.skywalking.oap.server.configuration.api.*;
+import org.apache.skywalking.oap.server.configuration.api.ConfigurationModule;
+import org.apache.skywalking.oap.server.configuration.api.DynamicConfigurationService;
import org.apache.skywalking.oap.server.core.CoreModule;
-import org.apache.skywalking.oap.server.core.server.*;
-import org.apache.skywalking.oap.server.library.module.*;
+import org.apache.skywalking.oap.server.core.server.GRPCHandlerRegister;
+import org.apache.skywalking.oap.server.core.server.JettyHandlerRegister;
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
+import org.apache.skywalking.oap.server.library.module.ModuleDefine;
+import org.apache.skywalking.oap.server.library.module.ModuleProvider;
+import org.apache.skywalking.oap.server.library.module.ModuleStartException;
+import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException;
import org.apache.skywalking.oap.server.receiver.sharing.server.SharingServerModule;
import org.apache.skywalking.oap.server.receiver.trace.module.TraceModule;
import org.apache.skywalking.oap.server.receiver.trace.provider.handler.v5.grpc.TraceSegmentServiceHandler;
import org.apache.skywalking.oap.server.receiver.trace.provider.handler.v5.rest.TraceSegmentServletHandler;
import org.apache.skywalking.oap.server.receiver.trace.provider.handler.v6.grpc.TraceSegmentReportServiceHandler;
-import org.apache.skywalking.oap.server.receiver.trace.provider.parser.*;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.ISegmentParserService;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.SegmentParse;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.SegmentParseV2;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.SegmentParserListenerManager;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.SegmentParserServiceImpl;
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.endpoint.MultiScopesSpanListener;
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.segment.SegmentSpanListener;
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.service.ServiceMappingSpanListener;
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.standardization.SegmentStandardizationWorker;
import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
+import java.io.IOException;
+
/**
* @author peng-yongsheng
*/
@@ -44,6 +55,7 @@ public class TraceModuleProvider extends ModuleProvider {
private SegmentParse.Producer segmentProducer;
private SegmentParseV2.Producer segmentProducerV2;
private DBLatencyThresholdsAndWatcher thresholds;
+ private UninstrumentedGatewaysConfig uninstrumentedGatewaysConfig;
public TraceModuleProvider() {
this.moduleConfig = new TraceServiceModuleConfig();
@@ -64,7 +76,10 @@ public class TraceModuleProvider extends ModuleProvider {
@Override public void prepare() throws ServiceNotProvidedException {
thresholds = new DBLatencyThresholdsAndWatcher(moduleConfig.getSlowDBAccessThreshold(), this);
+ uninstrumentedGatewaysConfig = new UninstrumentedGatewaysConfig(this);
+
moduleConfig.setDbLatencyThresholdsAndWatcher(thresholds);
+ moduleConfig.setUninstrumentedGatewaysConfig(uninstrumentedGatewaysConfig);
segmentProducer = new SegmentParse.Producer(getManager(), listenerManager(), moduleConfig);
segmentProducerV2 = new SegmentParseV2.Producer(getManager(), listenerManager(), moduleConfig);
@@ -89,6 +104,7 @@ public class TraceModuleProvider extends ModuleProvider {
JettyHandlerRegister jettyHandlerRegister = getManager().find(SharingServerModule.NAME).provider().getService(JettyHandlerRegister.class);
try {
dynamicConfigurationService.registerConfigChangeWatcher(thresholds);
+ dynamicConfigurationService.registerConfigChangeWatcher(uninstrumentedGatewaysConfig);
grpcHandlerRegister.addHandler(new TraceSegmentServiceHandler(segmentProducer));
grpcHandlerRegister.addHandler(new TraceSegmentReportServiceHandler(segmentProducerV2, getManager()));
diff --git a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/TraceServiceModuleConfig.java b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/TraceServiceModuleConfig.java
old mode 100644
new mode 100755
index b0ffbd6dcaa2231dd58b63221ca93a79e6ae228c..49d3c1bb1860a88a997ab51fd0ea78e9d1468557
--- a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/TraceServiceModuleConfig.java
+++ b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/TraceServiceModuleConfig.java
@@ -39,6 +39,7 @@ public class TraceServiceModuleConfig extends ModuleConfig {
*/
@Setter @Getter private String slowDBAccessThreshold = "default:200";
@Setter @Getter private DBLatencyThresholdsAndWatcher dbLatencyThresholdsAndWatcher;
+ @Setter @Getter private UninstrumentedGatewaysConfig uninstrumentedGatewaysConfig;
/**
* Analysis trace status.
*
diff --git a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/UninstrumentedGatewaysConfig.java b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/UninstrumentedGatewaysConfig.java
new file mode 100755
index 0000000000000000000000000000000000000000..5ed2b56b1746f3f369efbf3d2233232f613804f4
--- /dev/null
+++ b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/UninstrumentedGatewaysConfig.java
@@ -0,0 +1,159 @@
+/*
+ * 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.receiver.trace.provider;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.configuration.api.ConfigChangeWatcher;
+import org.apache.skywalking.oap.server.core.Const;
+import org.apache.skywalking.oap.server.library.util.ResourceUtils;
+import org.apache.skywalking.oap.server.receiver.trace.module.TraceModule;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.FileNotFoundException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import static java.util.Objects.isNull;
+
+/**
+ * @author kezhenxu94
+ */
+@Slf4j
+public class UninstrumentedGatewaysConfig extends ConfigChangeWatcher {
+ private final AtomicReference settingsString;
+ private volatile Map gatewayInstanceKeyedByAddress = Collections.emptyMap();
+
+ UninstrumentedGatewaysConfig(TraceModuleProvider provider) {
+ super(TraceModule.NAME, provider, "uninstrumentedGateways");
+ this.settingsString = new AtomicReference<>(Const.EMPTY_STRING);
+ final GatewayInfos defaultGateways = parseGatewaysFromFile("gateways.yml");
+ log.info("Default configured gateways: {}", defaultGateways);
+ onGatewaysUpdated(defaultGateways);
+ }
+
+ private void activeSetting(String config) {
+ if (log.isDebugEnabled()) {
+ log.debug("Updating using new static config: {}", config);
+ }
+ this.settingsString.set(config);
+ onGatewaysUpdated(parseGatewaysFromYml(config));
+ }
+
+ @Override
+ public void notify(ConfigChangeEvent value) {
+ if (EventType.DELETE.equals(value.getEventType())) {
+ activeSetting("");
+ } else {
+ activeSetting(value.getNewValue());
+ }
+ }
+
+ @Override
+ public String value() {
+ return settingsString.get();
+ }
+
+ private void onGatewaysUpdated(final GatewayInfos gateways) {
+ log.info("Updating uninstrumented gateways with: {}", gateways);
+ if (isNull(gateways)) {
+ gatewayInstanceKeyedByAddress = Collections.emptyMap();
+ } else {
+ gatewayInstanceKeyedByAddress =
+ StreamSupport.stream(gateways.spliterator(), false)
+ .flatMap(instance -> instance.getInstances().stream())
+ .collect(Collectors.toMap(GatewayInstanceInfo::getAddress, Function.identity()));
+ }
+ }
+
+ public boolean isAddressConfiguredAsGateway(final String address) {
+ final boolean isConfiguredAsGateway = gatewayInstanceKeyedByAddress.get(address) != null;
+ if (log.isDebugEnabled()) {
+ log.debug("Address [{}] is configured as gateway: {}", address, isConfiguredAsGateway);
+ }
+ return isConfiguredAsGateway;
+ }
+
+ private GatewayInfos parseGatewaysFromFile(final String file) {
+ try {
+ final Reader reader = ResourceUtils.read(file);
+ return new Yaml().loadAs(reader, GatewayInfos.class);
+ } catch (FileNotFoundException e) {
+ log.error("Cannot load gateways from: {}", file, e);
+ }
+ return GatewayInfos.EMPTY;
+ }
+
+ private GatewayInfos parseGatewaysFromYml(final String ymlContent) {
+ try {
+ return new Yaml().loadAs(ymlContent, GatewayInfos.class);
+ } catch (Exception e) {
+ log.error("Failed to parse yml content as gateways: \n{}", ymlContent, e);
+ }
+ return GatewayInfos.EMPTY;
+ }
+
+ @Getter
+ @Setter
+ @ToString
+ public static class GatewayInfo {
+ private String name;
+ private List instances;
+ }
+
+ @ToString
+ public static class GatewayInfos implements Iterable {
+ static final GatewayInfos EMPTY = new GatewayInfos();
+
+ @Getter
+ @Setter
+ private Collection gateways;
+
+ GatewayInfos() {
+ gateways = new ArrayList<>();
+ }
+
+ @Override
+ public Iterator iterator() {
+ return gateways.iterator();
+ }
+ }
+
+ @Getter
+ @Setter
+ @ToString
+ public static class GatewayInstanceInfo {
+ private String host;
+ private Integer port;
+
+ String getAddress() {
+ return getHost() + ":" + (isNull(getPort()) || getPort() <= 0 ? "80" : getPort());
+ }
+ }
+}
diff --git a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/parser/listener/endpoint/MultiScopesSpanListener.java b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/parser/listener/endpoint/MultiScopesSpanListener.java
old mode 100644
new mode 100755
index be6077d3b044d38346d3a39f2274a1c7e0882732..5fd0af120b7884729d1b11465004bd3350e0736a
--- a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/parser/listener/endpoint/MultiScopesSpanListener.java
+++ b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/parser/listener/endpoint/MultiScopesSpanListener.java
@@ -18,20 +18,31 @@
package org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.endpoint;
-import java.util.*;
import org.apache.skywalking.apm.network.common.KeyStringValuePair;
import org.apache.skywalking.apm.network.language.agent.*;
import org.apache.skywalking.apm.util.StringUtil;
import org.apache.skywalking.oap.server.core.*;
+import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
import org.apache.skywalking.oap.server.core.cache.*;
import org.apache.skywalking.oap.server.core.source.*;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
-import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
-import org.apache.skywalking.oap.server.receiver.trace.provider.*;
+import org.apache.skywalking.oap.server.receiver.trace.provider.DBLatencyThresholdsAndWatcher;
+import org.apache.skywalking.oap.server.receiver.trace.provider.TraceServiceModuleConfig;
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.SpanTags;
-import org.apache.skywalking.oap.server.receiver.trace.provider.parser.decorator.*;
-import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.*;
-import org.slf4j.*;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.decorator.ReferenceDecorator;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.decorator.SegmentCoreInfo;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.decorator.SpanDecorator;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.EntrySpanListener;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.ExitSpanListener;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.GlobalTraceIdsListener;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.SpanListener;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.SpanListenerFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
import static java.util.Objects.nonNull;
@@ -57,6 +68,7 @@ public class MultiScopesSpanListener implements EntrySpanListener, ExitSpanListe
private final List exitSourceBuilders;
private final List slowDatabaseAccesses;
private final TraceServiceModuleConfig config;
+ private final NetworkAddressInventoryCache networkAddressInventoryCache;
private SpanDecorator entrySpanDecorator;
private long minuteTimeBucket;
private String traceId;
@@ -69,6 +81,7 @@ public class MultiScopesSpanListener implements EntrySpanListener, ExitSpanListe
this.instanceInventoryCache = moduleManager.find(CoreModule.NAME).provider().getService(ServiceInstanceInventoryCache.class);
this.serviceInventoryCache = moduleManager.find(CoreModule.NAME).provider().getService(ServiceInventoryCache.class);
this.endpointInventoryCache = moduleManager.find(CoreModule.NAME).provider().getService(EndpointInventoryCache.class);
+ this.networkAddressInventoryCache = moduleManager.find(CoreModule.NAME).provider().getService(NetworkAddressInventoryCache.class);
this.config = config;
this.traceId = null;
}
@@ -87,9 +100,12 @@ public class MultiScopesSpanListener implements EntrySpanListener, ExitSpanListe
SourceBuilder sourceBuilder = new SourceBuilder();
sourceBuilder.setSourceEndpointId(reference.getParentEndpointId());
- if (spanDecorator.getSpanLayer().equals(SpanLayer.MQ)) {
- int serviceIdByPeerId = serviceInventoryCache.getServiceId(reference.getNetworkAddressId());
- int instanceIdByPeerId = instanceInventoryCache.getServiceInstanceId(serviceIdByPeerId, reference.getNetworkAddressId());
+ final int networkAddressId = reference.getNetworkAddressId();
+ final int serviceIdByPeerId = serviceInventoryCache.getServiceId(networkAddressId);
+ final String address = networkAddressInventoryCache.get(networkAddressId).getName();
+
+ if (spanDecorator.getSpanLayer().equals(SpanLayer.MQ) || config.getUninstrumentedGatewaysConfig().isAddressConfiguredAsGateway(address)) {
+ int instanceIdByPeerId = instanceInventoryCache.getServiceInstanceId(serviceIdByPeerId, networkAddressId);
sourceBuilder.setSourceServiceInstanceId(instanceIdByPeerId);
sourceBuilder.setSourceServiceId(serviceIdByPeerId);
} else {
diff --git a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/parser/listener/service/ServiceMappingSpanListener.java b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/parser/listener/service/ServiceMappingSpanListener.java
old mode 100644
new mode 100755
index 338a1cd82af68c059c8eaba15e558afa7ed71051..7010b8815a813417cd4661476d041c6e83f82c7d
--- a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/parser/listener/service/ServiceMappingSpanListener.java
+++ b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/trace/provider/parser/listener/service/ServiceMappingSpanListener.java
@@ -18,17 +18,25 @@
package org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.service;
-import java.util.*;
-import lombok.*;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.skywalking.apm.network.language.agent.SpanLayer;
import org.apache.skywalking.oap.server.core.CoreModule;
+import org.apache.skywalking.oap.server.core.cache.NetworkAddressInventoryCache;
import org.apache.skywalking.oap.server.core.cache.ServiceInventoryCache;
import org.apache.skywalking.oap.server.core.register.service.IServiceInventoryRegister;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.receiver.trace.provider.TraceServiceModuleConfig;
-import org.apache.skywalking.oap.server.receiver.trace.provider.parser.decorator.*;
-import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.*;
-import org.slf4j.*;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.decorator.SegmentCoreInfo;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.decorator.SpanDecorator;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.EntrySpanListener;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.SpanListener;
+import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.SpanListenerFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.LinkedList;
+import java.util.List;
/**
* @author peng-yongsheng
@@ -38,12 +46,17 @@ public class ServiceMappingSpanListener implements EntrySpanListener {
private static final Logger logger = LoggerFactory.getLogger(ServiceMappingSpanListener.class);
private final IServiceInventoryRegister serviceInventoryRegister;
+ private final TraceServiceModuleConfig config;
private final ServiceInventoryCache serviceInventoryCache;
- private List serviceMappings = new LinkedList<>();
+ private final NetworkAddressInventoryCache networkAddressInventoryCache;
+ private final List serviceMappings = new LinkedList<>();
+ private final List servicesToResetMapping = new LinkedList<>();
- private ServiceMappingSpanListener(ModuleManager moduleManager) {
+ private ServiceMappingSpanListener(ModuleManager moduleManager, TraceServiceModuleConfig config) {
this.serviceInventoryCache = moduleManager.find(CoreModule.NAME).provider().getService(ServiceInventoryCache.class);
+ this.networkAddressInventoryCache = moduleManager.find(CoreModule.NAME).provider().getService(NetworkAddressInventoryCache.class);
this.serviceInventoryRegister = moduleManager.find(CoreModule.NAME).provider().getService(IServiceInventoryRegister.class);
+ this.config = config;
}
@Override public boolean containsPoint(Point point) {
@@ -58,9 +71,16 @@ public class ServiceMappingSpanListener implements EntrySpanListener {
if (!spanDecorator.getSpanLayer().equals(SpanLayer.MQ)) {
if (spanDecorator.getRefsCount() > 0) {
for (int i = 0; i < spanDecorator.getRefsCount(); i++) {
- int serviceId = serviceInventoryCache.getServiceId(spanDecorator.getRefs(i).getNetworkAddressId());
- int mappingServiceId = serviceInventoryCache.get(serviceId).getMappingServiceId();
- if (mappingServiceId != segmentCoreInfo.getServiceId()) {
+ int networkAddressId = spanDecorator.getRefs(i).getNetworkAddressId();
+ String address = networkAddressInventoryCache.get(networkAddressId).getName();
+ int serviceId = serviceInventoryCache.getServiceId(networkAddressId);
+
+ if (config.getUninstrumentedGatewaysConfig().isAddressConfiguredAsGateway(address)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("{} is configured as gateway, will reset its mapping service id", serviceId);
+ }
+ servicesToResetMapping.add(serviceId);
+ } else {
ServiceMapping serviceMapping = new ServiceMapping();
serviceMapping.setServiceId(serviceId);
serviceMapping.setMappingServiceId(segmentCoreInfo.getServiceId());
@@ -78,18 +98,24 @@ public class ServiceMappingSpanListener implements EntrySpanListener {
}
serviceInventoryRegister.updateMapping(serviceMapping.getServiceId(), serviceMapping.getMappingServiceId());
});
+ servicesToResetMapping.forEach(serviceId -> {
+ if (logger.isDebugEnabled()) {
+ logger.debug("service mapping listener build, reset mapping of service id: {}", serviceId);
+ }
+ serviceInventoryRegister.resetMapping(serviceId);
+ });
}
public static class Factory implements SpanListenerFactory {
@Override public SpanListener create(ModuleManager moduleManager, TraceServiceModuleConfig config) {
- return new ServiceMappingSpanListener(moduleManager);
+ return new ServiceMappingSpanListener(moduleManager, config);
}
}
@Setter
@Getter
- private class ServiceMapping {
+ private static class ServiceMapping {
private int serviceId;
private int mappingServiceId;
}
diff --git a/oap-server/server-receiver-plugin/zipkin-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/zipkin/analysis/transform/SpringSleuthSegmentBuilderTest.java b/oap-server/server-receiver-plugin/zipkin-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/zipkin/analysis/transform/SpringSleuthSegmentBuilderTest.java
index 96e51ca9737d6a9d00959e5b9bbdd88db949f00b..b4ecf2ee0ea6a4495cdba720f3e9d92d45da1bad 100644
--- a/oap-server/server-receiver-plugin/zipkin-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/zipkin/analysis/transform/SpringSleuthSegmentBuilderTest.java
+++ b/oap-server/server-receiver-plugin/zipkin-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/zipkin/analysis/transform/SpringSleuthSegmentBuilderTest.java
@@ -78,6 +78,9 @@ public class SpringSleuthSegmentBuilderTest implements SegmentListener {
}
+ @Override public void resetMapping(final int serviceId) {
+
+ }
};
IServiceInstanceInventoryRegister instanceIDService = new IServiceInstanceInventoryRegister() {
@@ -193,4 +196,4 @@ public class SpringSleuthSegmentBuilderTest implements SegmentListener {
Assert.assertEquals(-1, spanObject.getParentSpanId());
Assert.assertEquals(SpanType.Entry, spanObject.getSpanType());
}
-}
\ No newline at end of file
+}
diff --git a/oap-server/server-starter/src/main/assembly/assembly.xml b/oap-server/server-starter/src/main/assembly/assembly.xml
old mode 100644
new mode 100755
diff --git a/oap-server/server-starter/src/main/assembly/gateways.yml b/oap-server/server-starter/src/main/assembly/gateways.yml
new file mode 100755
index 0000000000000000000000000000000000000000..9b501a7d6bd3a2e1f30a273948cd325dc5d5d132
--- /dev/null
+++ b/oap-server/server-starter/src/main/assembly/gateways.yml
@@ -0,0 +1,20 @@
+# 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.
+
+#gateways:
+# - name: proxy0
+# instances:
+# - host: 127.0.0.1 # the host/ip of this gateway instance
+# port: 9099 # the port of this gateway instance, defaults to 80
diff --git a/pom.xml b/pom.xml
index e7df6278aea7c7ae51e1ac011cb4e73ff0a2c005..6aaf68414dfc088af6948b1095019618bf6860cc 100755
--- a/pom.xml
+++ b/pom.xml
@@ -424,6 +424,8 @@
.mvn/wrapper/maven-wrapper.properties
tools/dependencies/known-oap-backend-dependencies.txt
apm-checkstyle/CHECKSTYLE_HEAD
+
+ .m2/**
diff --git a/test/e2e/e2e-cluster/consumer/src/main/java/org/apache/skywalking/e2e/cluster/TestController.java b/test/e2e/e2e-cluster/consumer/src/main/java/org/apache/skywalking/e2e/cluster/TestController.java
index c59f3d315f693e6d2cb9dd674be51f33944b3989..a50088b4138750b1c5a3b63d59704db94f8e9426 100644
--- a/test/e2e/e2e-cluster/consumer/src/main/java/org/apache/skywalking/e2e/cluster/TestController.java
+++ b/test/e2e/e2e-cluster/consumer/src/main/java/org/apache/skywalking/e2e/cluster/TestController.java
@@ -43,7 +43,7 @@ public class TestController {
public User createAuthor(@RequestBody final User user) throws InterruptedException {
Thread.sleep(1000L);
final ResponseEntity response = restTemplate.postForEntity(
- "http://localhost:9090/e2e/users", user, User.class
+ "http://127.0.0.1:9099/e2e/users", user, User.class
);
return response.getBody();
}
diff --git a/test/e2e/e2e-cluster/gateway/pom.xml b/test/e2e/e2e-cluster/gateway/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..afc8ff353a5478851bb8bd454df3630aec748599
--- /dev/null
+++ b/test/e2e/e2e-cluster/gateway/pom.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+ e2e-cluster
+ org.apache.skywalking
+ 1.0.0
+
+ 4.0.0
+
+ gateway
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${spring.boot.version}
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-zuul
+ ${spring.cloud.version}
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.version}
+
+ true
+ true
+ true
+
+
+
+
+ repackage
+
+
+
+
+
+
+
diff --git a/test/e2e/e2e-cluster/gateway/src/main/java/org/apache/skywalking/e2e/GatewayApplication.java b/test/e2e/e2e-cluster/gateway/src/main/java/org/apache/skywalking/e2e/GatewayApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..a4e4311f2c550c8bbdc0e93d31e7240e65946a63
--- /dev/null
+++ b/test/e2e/e2e-cluster/gateway/src/main/java/org/apache/skywalking/e2e/GatewayApplication.java
@@ -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.
+ */
+
+package org.apache.skywalking.e2e;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
+
+/**
+ * @author kezhenxu94
+ */
+@EnableZuulProxy
+@SpringBootApplication
+public class GatewayApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(GatewayApplication.class, args);
+ }
+}
diff --git a/test/e2e/e2e-cluster/gateway/src/main/resources/application.yml b/test/e2e/e2e-cluster/gateway/src/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..32131fc57e5af1dd5ade61254ecf4b5d0550249f
--- /dev/null
+++ b/test/e2e/e2e-cluster/gateway/src/main/resources/application.yml
@@ -0,0 +1,28 @@
+# 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.
+
+server:
+ port: 9099
+
+spring:
+ application:
+ name: SkyWalking
+
+zuul:
+ ignoredServices: '*'
+ routes:
+ api:
+ path: /e2e/users
+ url: http://127.0.0.1:9090
diff --git a/test/e2e/e2e-cluster/pom.xml b/test/e2e/e2e-cluster/pom.xml
index 757863d453c34f8c3117eda541de8a2577daa106..f9c4895549f29d4bec93616a658476d8c85547e1 100644
--- a/test/e2e/e2e-cluster/pom.xml
+++ b/test/e2e/e2e-cluster/pom.xml
@@ -33,6 +33,7 @@
provider
consumer
+ gateway
test-runner
diff --git a/test/e2e/e2e-cluster/test-runner/pom.xml b/test/e2e/e2e-cluster/test-runner/pom.xml
index af90ce315fed2b8da6d0d7143c296a10518fdf1c..38c7d36b1585729fb18d1a3e9f17f54a0bbe10e0 100755
--- a/test/e2e/e2e-cluster/test-runner/pom.xml
+++ b/test/e2e/e2e-cluster/test-runner/pom.xml
@@ -38,6 +38,12 @@
${project.version}
+
+ org.apache.skywalking
+ gateway
+ ${project.version}
+
+
org.apache.skywalking
provider
@@ -53,8 +59,9 @@
- provider
- consumer
+ provider
+ consumer
+ gateway
1.1
skywalking-e2e-container-${build.id}-cluster
@@ -99,7 +106,7 @@
binding to port
-
+
@@ -117,22 +124,22 @@
- ${service0.name}-${project.version}.jar
+ ${provider.name}-${project.version}.jar
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800
- -DSW_AGENT_NAME=${service0.name}
+ -DSW_AGENT_NAME=${provider.name}
--server.port=9090
- ${service1.name}-${project.version}.jar
+ ${consumer.name}-${project.version}.jar
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11801
- -DSW_AGENT_NAME=${service1.name}
+ -DSW_AGENT_NAME=${consumer.name}
--server.port=9091
@@ -156,10 +163,13 @@
../../../../dist-for-cluster/apache-skywalking-apm-bin:/sw
- ../${service0.name}/target/${service0.name}-${project.version}.jar:/home/${service0.name}-${project.version}.jar
+ ../${gateway.name}/target/${gateway.name}-${project.version}.jar:/home/${gateway.name}-${project.version}.jar
+
+
+ ../${provider.name}/target/${provider.name}-${project.version}.jar:/home/${provider.name}-${project.version}.jar
- ../${service1.name}/target/${service1.name}-${project.version}.jar:/home/${service1.name}-${project.version}.jar
+ ../${consumer.name}/target/${consumer.name}-${project.version}.jar:/home/${consumer.name}-${project.version}.jar
${project.basedir}/src/docker/rc.d:/rc.d:ro
@@ -171,7 +181,7 @@
SkyWalking e2e container is ready for tests
-
+
diff --git a/test/e2e/e2e-cluster/test-runner/src/docker/rc.d/rc0-prepare.sh b/test/e2e/e2e-cluster/test-runner/src/docker/rc.d/rc0-prepare.sh
index 5baf02b512a68c6e89de100556e7f228e909b523..45331e2ed79beb156f7a39cec46b24ec13030b78 100755
--- a/test/e2e/e2e-cluster/test-runner/src/docker/rc.d/rc0-prepare.sh
+++ b/test/e2e/e2e-cluster/test-runner/src/docker/rc.d/rc0-prepare.sh
@@ -22,7 +22,17 @@ if test "${MODE}" = "cluster"; then
# substitute application.yml to be capable of cluster mode
cd ${SW_HOME}/config \
&& awk -f /clusterize.awk application.yml > clusterized_app.yml \
- && mv clusterized_app.yml application.yml
+ && mv clusterized_app.yml application.yml \
+ && echo '
+gateways:
+ - name: proxy0
+ instances:
+ - host: 127.0.0.1 # the host/ip of this gateway instance
+ port: 9099 # the port of this gateway instance, defaults to 80
+' > gateways.yml \
+ && sed '//a\
+ \n' log4j2.xml > log4j2debuggable.xml \
+ && mv log4j2debuggable.xml log4j2.xml
cd ${SW_HOME}/webapp \
&& awk '/^\s+listOfServers:/ {gsub("listOfServers:.*", "listOfServers: 127.0.0.1:12800,127.0.0.1:12801", $0)} {print}' webapp.yml > clusterized_webapp.yml \
diff --git a/test/e2e/e2e-cluster/test-runner/src/docker/rc.d/rc1-startup.sh b/test/e2e/e2e-cluster/test-runner/src/docker/rc.d/rc1-startup.sh
index 06576f29694564f3b6109ea68f68faea63324d60..ee78788d24b1f1e1b9dcdffe5620c5dd5e5d2a60 100755
--- a/test/e2e/e2e-cluster/test-runner/src/docker/rc.d/rc1-startup.sh
+++ b/test/e2e/e2e-cluster/test-runner/src/docker/rc.d/rc1-startup.sh
@@ -16,12 +16,27 @@
#!/usr/bin/env bash
+echo 'starting gateway service...' \
+ && java -jar /home/gateway-1.0.0.jar 2>&1 > /tmp/gateway.log &
+
+check_tcp 127.0.0.1 \
+ 9099 \
+ 60 \
+ 10 \
+ 'waiting for the gateway service to be ready'
+
+if [[ $? -ne 0 ]]; then
+ echo "gateway service failed to start in 60 * 10 seconds: "
+ cat /tmp/gateway.log
+ exit 1
+fi
+
echo 'starting OAP server...' \
&& SW_STORAGE_ES_BULK_ACTIONS=1 \
- && SW_STORAGE_ES_FLUSH_INTERVAL=1 \
- && SW_RECEIVER_BUFFER_PATH=/tmp/oap/trace_buffer1 \
- && SW_SERVICE_MESH_BUFFER_PATH=/tmp/oap/mesh_buffer1 \
- && start_oap 'init'
+ SW_STORAGE_ES_FLUSH_INTERVAL=1 \
+ SW_RECEIVER_BUFFER_PATH=/tmp/oap/trace_buffer1 \
+ SW_SERVICE_MESH_BUFFER_PATH=/tmp/oap/mesh_buffer1 \
+ start_oap 'init'
echo 'starting Web app...' \
&& start_webapp '0.0.0.0' 8081
@@ -30,12 +45,12 @@ if test "${MODE}" = "cluster"; then
# start another OAP server in a different port
echo 'starting OAP server...' \
&& SW_CORE_GRPC_PORT=11801 \
- && SW_CORE_REST_PORT=12801 \
- && SW_STORAGE_ES_BULK_ACTIONS=1 \
- && SW_STORAGE_ES_FLUSH_INTERVAL=1 \
- && SW_RECEIVER_BUFFER_PATH=/tmp/oap/trace_buffer2 \
- && SW_SERVICE_MESH_BUFFER_PATH=/tmp/oap/mesh_buffer2 \
- && start_oap 'no-init'
+ SW_CORE_REST_PORT=12801 \
+ SW_STORAGE_ES_BULK_ACTIONS=1 \
+ SW_STORAGE_ES_FLUSH_INTERVAL=1 \
+ SW_RECEIVER_BUFFER_PATH=/tmp/oap/trace_buffer2 \
+ SW_SERVICE_MESH_BUFFER_PATH=/tmp/oap/mesh_buffer2 \
+ start_oap 'no-init'
fi
echo 'starting instrumented services...' && start_instrumented_services
diff --git a/test/e2e/e2e-cluster/test-runner/src/test/java/org/apache/skywalking/e2e/ClusterVerificationITCase.java b/test/e2e/e2e-cluster/test-runner/src/test/java/org/apache/skywalking/e2e/ClusterVerificationITCase.java
old mode 100644
new mode 100755
index f4e84ae7d4b54152132c09d3b3635a1374abb478..668f3048d3260b477561592252db6badf058df8a
--- a/test/e2e/e2e-cluster/test-runner/src/test/java/org/apache/skywalking/e2e/ClusterVerificationITCase.java
+++ b/test/e2e/e2e-cluster/test-runner/src/test/java/org/apache/skywalking/e2e/ClusterVerificationITCase.java
@@ -45,7 +45,6 @@ import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
-import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -61,10 +60,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
-import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_ENDPOINT_METRICS;
-import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_INSTANCE_METRICS;
-import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_METRICS;
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.*;
/**
* @author kezhenxu94
@@ -118,18 +114,29 @@ public class ClusterVerificationITCase {
}
private void verifyTopo(LocalDateTime minutesAgo) throws Exception {
- final TopoData topoData = queryClient.topo(
- new TopoQuery()
- .stepByMinute()
- .start(minutesAgo)
- .end(LocalDateTime.now(ZoneOffset.UTC).plusMinutes(1))
- );
-
- InputStream expectedInputStream =
- new ClassPathResource("expected-data/org.apache.skywalking.e2e.ClusterVerificationITCase.topo.yml").getInputStream();
-
- final TopoMatcher topoMatcher = yaml.loadAs(expectedInputStream, TopoMatcher.class);
- topoMatcher.verify(topoData);
+ boolean valid = false;
+ while (!valid) {
+ try {
+ final TopoData topoData = queryClient.topo(
+ new TopoQuery()
+ .stepByMinute()
+ .start(minutesAgo)
+ .end(LocalDateTime.now(ZoneOffset.UTC).plusMinutes(1))
+ );
+ LOGGER.info("Actual topology: {}", topoData);
+
+ InputStream expectedInputStream =
+ new ClassPathResource("expected-data/org.apache.skywalking.e2e.ClusterVerificationITCase.topo.yml").getInputStream();
+
+ final TopoMatcher topoMatcher = yaml.loadAs(expectedInputStream, TopoMatcher.class);
+ topoMatcher.verify(topoData);
+ valid = true;
+ } catch (Throwable t) {
+ LOGGER.warn(t.getMessage(), t);
+ generateTraffic();
+ Thread.sleep(retryInterval);
+ }
+ }
}
private void verifyServices(LocalDateTime minutesAgo) throws Exception {
@@ -333,14 +340,17 @@ public class ClusterVerificationITCase {
}
private void generateTraffic() {
- final Map user = new HashMap<>();
- user.put("name", "SkyWalking");
- final ResponseEntity responseEntity = restTemplate.postForEntity(
- instrumentedServiceUrl + "/e2e/users",
- user,
- String.class
- );
- LOGGER.info("responseEntity: {}, {}", responseEntity.getStatusCode(), responseEntity.getBody());
- assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
+ try {
+ final Map user = new HashMap<>();
+ user.put("name", "SkyWalking");
+ final ResponseEntity responseEntity = restTemplate.postForEntity(
+ instrumentedServiceUrl + "/e2e/users",
+ user,
+ String.class
+ );
+ LOGGER.info("responseEntity: {}, {}", responseEntity.getStatusCode(), responseEntity.getBody());
+ } catch (Throwable t) {
+ LOGGER.warn(t.getMessage(), t);
+ }
}
}
diff --git a/test/e2e/e2e-cluster/test-runner/src/test/resources/expected-data/org.apache.skywalking.e2e.ClusterVerificationITCase.topo.yml b/test/e2e/e2e-cluster/test-runner/src/test/resources/expected-data/org.apache.skywalking.e2e.ClusterVerificationITCase.topo.yml
index 9f74cfce6a420901a0890eae24bb82ca2f4d3f78..8f58605cf42613853ffaf15fd83eff6a7268a4b6 100644
--- a/test/e2e/e2e-cluster/test-runner/src/test/resources/expected-data/org.apache.skywalking.e2e.ClusterVerificationITCase.topo.yml
+++ b/test/e2e/e2e-cluster/test-runner/src/test/resources/expected-data/org.apache.skywalking.e2e.ClusterVerificationITCase.topo.yml
@@ -27,6 +27,9 @@ nodes:
- id: not null
name: "localhost:-1"
type: H2
+ - id: not null
+ name: "127.0.0.1:9099"
+ type: Unknown
calls:
- id: not null
source: not null
@@ -37,3 +40,6 @@ calls:
- id: not null
source: not null
target: not null
+ - id: not null
+ source: not null
+ target: not null
diff --git a/test/e2e/pom.xml b/test/e2e/pom.xml
index 7017c88aa009df436737d3beaa993ba7bde223f3..21a3ffe029b2f7a0053f3c52992f15fc6f367f5f 100644
--- a/test/e2e/pom.xml
+++ b/test/e2e/pom.xml
@@ -46,6 +46,7 @@
UTF-8
2.1.5.RELEASE
+ 2.1.2.RELEASE
2.9.7
4.12
2.9.7