未验证 提交 aa217656 编写于 作者: J Jared Tan 提交者: GitHub

support http api for upstream trace. (#4399)

* support http api.

* e2e
Co-authored-by: wu-sheng's avatar吴晟 Wu Sheng <wu.sheng@foxmail.com>
Co-authored-by: Nkezhenxu94 <kezhenxu94@apache.org>
上级 0df2d0a5
......@@ -116,6 +116,8 @@ jobs:
./mvnw --batch-mode -f test/e2e/pom.xml -pl e2e-base clean install
- name: 6.x Agents & 7.x Backend
run: export E2E_VERSION=jdk8-1.5 && bash -x test/e2e/run.sh e2e-6.x-agent-7.x-oap-compatibility
- name: Http API with Nginx Lua Tests In Single Node Mode(JDK8)
run: export E2E_VERSION=jdk8-1.5 && bash -x test/e2e/run.sh e2e-http-api-with-nginx-lua
Profile:
runs-on: ubuntu-latest
......
......@@ -20,3 +20,4 @@ OALLexer.tokens
.externalToolBuilders
/test/plugin/dist
/test/plugin/workspace
e2e-*
# HTTP API Protocol
HTTP API Protocol defines the API data format, including api request and response data format.
### Do register
Detail information about data format can be found in [Register service](https://github.com/apache/skywalking-data-collect-protocol/tree/master/register/Register.proto).
And register steps followings [SkyWalking Trace Data Protocol v2](Trace-Data-Protocol-v2.md).
- Service Register
> POST http://localhost:12800/v2/service/register
Input:
```json
{
"services": [
{
"type": "normal",
"serviceName": "Service Name"
}
]
}
```
Output JSON Array:
```json
[
{
"key": "Service Name",
"value": 2
}
]
```
- Service instance Register
> POST http://localhost:12800/v2/instance/register
Input:
```json
{
"instances": [
{
"time": 1582428603392,
"instanceUUID": "NAME:Service Instance Name",
"properties": [
{
"key": "language",
"value": "Lua"
}
],
"serviceId": 2
}
]
}
```
OutPut:
```json
[
{
"key": "NAME:Service Instance Name",
"value": 0
}
]
```
- Service instance heartbeat
> POST http://localhost:12800/v2/instance/heartbeat
Input:
```json
{
"serviceInstanceId":20,
"time": 1582428603392,
"serviceInstanceUUID":"NAME:Service Instance Name"
}
```
OutPut:
```json
{}
```
If your instance does not exist, you need to clean your local service instance metadata in your application and re-do register:
```json
{
"commands": [
{
"command": "ServiceMetadataReset",
"args": [
{
"key": "SerialNumber",
"value": "44bd2664-03c7-46bc-8652-52fcde0e7699"
}
]
}
]
}
```
## Trace Report
### POST http://localhost:12800/v2/segments
Input:
```json
{
"spans": [
{
"operationName": "/tier2/lb",
"startTime": 1582461179910,
"tags": [],
"endTime": 1582461179922,
"spanType": "Exit",
"logs":[],
"spanId": 1,
"isError": false,
"parentSpanId": 0,
"componentId": 6000,
"peer": "User Service Name-nginx:upstream_ip:port",
"spanLayer": "HTTP"
},
{
"operationName": "/tier2/lb",
"startTime": 1582461179910,
"tags": [
{
"key": "http.method",
"value": "GET"
},
{
"key": "http.params",
"value": "http://127.0.0.1/tier2/lb"
}
],
"endTime": 1582461179922,
"spanType": "Entry",
"logs": [],
"spanId": 0,
"isError": false,
"parentSpanId": -1,
"componentId": 6000,
"refs": [
{
"parentTraceSegmentId": {
"idParts": [
1582461179038,
794206293,
69887
]
},
"parentEndpointId": 0,
"entryEndpointId": 0,
"parentServiceInstanceId": 1,
"parentEndpoint": "/ingress",
"networkAddress": "#User Service Name-nginx:upstream_ip:port",
"parentSpanId": 1,
"entryServiceInstanceId": 1,
"networkAddressId": 0,
"entryEndpoint": "/ingress"
}
],
"spanLayer": "HTTP"
}
],
"serviceInstanceId": 1,
"serviceId": 1,
"traceSegmentId": {
"idParts": [
1582461179044,
794206293,
69887
]
},
"globalTraceIds": [
{
"idParts": [
1582461179038,
794206293,
69887
]
}
]
}
```
OutPut:
```json
```
\ No newline at end of file
......@@ -7,6 +7,9 @@ Trace data protocol is defined and provided in [gRPC format](https://github.com/
For each agent/SDK, it needs to register service id and service instance id before reporting any kind of trace
or metrics data.
Since SkyWalking v7.x, SkyWalking provided register and uplink trace data through HTTP API way.
[HTTP API Protocol](HTTP-API-Protocol.md) defined the API data format.
### Step 1. Do register
[Register service](https://github.com/apache/skywalking-data-collect-protocol/tree/master/register/Register.proto) takes charge of
all register methods. At step 1, we need `doServiceRegister`, then `doServiceInstanceRegister`.
......
......@@ -90,6 +90,7 @@
<javaassist.version>3.25.0-GA</javaassist.version>
<zookeeper.image.version>3.5</zookeeper.image.version>
<protobuf-java-util.version>3.11.4</protobuf-java-util.version>
</properties>
......@@ -263,6 +264,13 @@
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>${protobuf-java-util.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
......
......@@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.library.server.jetty;
import com.google.gson.JsonElement;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
......@@ -84,25 +85,25 @@ public abstract class JettyJsonHandler extends JettyHandler {
@Override
protected final void doDelete(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
HttpServletResponse resp) throws ServletException, IOException {
super.doDelete(req, resp);
}
@Override
protected final void doOptions(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
HttpServletResponse resp) throws ServletException, IOException {
super.doOptions(req, resp);
}
@Override
protected final void doTrace(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
HttpServletResponse resp) throws ServletException, IOException {
super.doTrace(req, resp);
}
@Override
protected final void service(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
}
......@@ -189,4 +190,14 @@ public abstract class JettyJsonHandler extends JettyHandler {
out.flush();
out.close();
}
public String getJsonBody(HttpServletRequest req) throws IOException {
StringBuffer stringBuffer = new StringBuffer();
String line = null;
BufferedReader reader = req.getReader();
while ((line = reader.readLine()) != null) {
stringBuffer.append(line);
}
return stringBuffer.toString();
}
}
......@@ -31,6 +31,7 @@
<properties>
<ststem-rules.version>1.18.0</ststem-rules.version>
<protobuf-java.version>3.11.4</protobuf-java.version>
</properties>
<dependencies>
......@@ -53,5 +54,16 @@
<version>${ststem-rules.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf-java.version}</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
</dependency>
</dependencies>
</project>
/*
* 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.library.util;
import com.google.protobuf.Message;
import com.google.protobuf.util.JsonFormat;
import java.io.IOException;
public class ProtoBufJsonUtils {
public static String toJSON(Message sourceMessage) throws IOException {
return JsonFormat.printer().print(sourceMessage);
}
/**
* Extract data from a JSON String and use them to construct a Protocol Buffers Message.
*
* @param json A JSON data string to parse
* @param targetBuilder A Message builder to use to construct the resulting Message
* @throws com.google.protobuf.InvalidProtocolBufferException Thrown in case of invalid Message data
*/
public static void fromJSON(String json, Message.Builder targetBuilder) throws IOException {
JsonFormat.parser()
.usingTypeRegistry(JsonFormat.TypeRegistry.newBuilder()
.add(targetBuilder.getDescriptorForType())
.build())
.ignoringUnknownFields()
.merge(json, targetBuilder);
}
}
......@@ -20,12 +20,16 @@ package org.apache.skywalking.oap.server.receiver.register.provider;
import org.apache.skywalking.oap.server.core.CoreModule;
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.receiver.register.module.RegisterModule;
import org.apache.skywalking.oap.server.receiver.register.provider.handler.v6.grpc.RegisterServiceHandler;
import org.apache.skywalking.oap.server.receiver.register.provider.handler.v6.grpc.ServiceInstancePingServiceHandler;
import org.apache.skywalking.oap.server.receiver.register.provider.handler.v6.rest.ServiceInstancePingServletHandler;
import org.apache.skywalking.oap.server.receiver.register.provider.handler.v6.rest.ServiceInstanceRegisterServletHandler;
import org.apache.skywalking.oap.server.receiver.register.provider.handler.v6.rest.ServiceRegisterServletHandler;
import org.apache.skywalking.oap.server.receiver.sharing.server.SharingServerModule;
public class RegisterModuleProvider extends ModuleProvider {
......@@ -56,6 +60,13 @@ public class RegisterModuleProvider extends ModuleProvider {
.getService(GRPCHandlerRegister.class);
grpcHandlerRegister.addHandler(new RegisterServiceHandler(getManager()));
grpcHandlerRegister.addHandler(new ServiceInstancePingServiceHandler(getManager()));
JettyHandlerRegister jettyHandlerRegister = getManager().find(SharingServerModule.NAME)
.provider()
.getService(JettyHandlerRegister.class);
jettyHandlerRegister.addHandler(new ServiceRegisterServletHandler(getManager()));
jettyHandlerRegister.addHandler(new ServiceInstanceRegisterServletHandler(getManager()));
jettyHandlerRegister.addHandler(new ServiceInstancePingServletHandler(getManager()));
}
@Override
......
/*
* 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.register.provider.handler.v6.rest;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.io.IOException;
import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
import org.apache.skywalking.apm.network.common.Command;
import org.apache.skywalking.apm.network.common.Commands;
import org.apache.skywalking.apm.network.register.v2.ServiceInstancePingPkg;
import org.apache.skywalking.apm.network.trace.component.command.ServiceResetCommand;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.cache.ServiceInstanceInventoryCache;
import org.apache.skywalking.oap.server.core.command.CommandService;
import org.apache.skywalking.oap.server.core.register.ServiceInstanceInventory;
import org.apache.skywalking.oap.server.core.register.service.IServiceInstanceInventoryRegister;
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.library.server.jetty.ArgumentsParseException;
import org.apache.skywalking.oap.server.library.server.jetty.JettyJsonHandler;
import org.apache.skywalking.oap.server.library.util.ProtoBufJsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ServiceInstancePingServletHandler extends JettyJsonHandler {
private static final Logger logger = LoggerFactory.getLogger(ServiceInstancePingServletHandler.class);
private final IServiceInstanceInventoryRegister serviceInstanceInventoryRegister;
private final ServiceInstanceInventoryCache serviceInstanceInventoryCache;
private final IServiceInventoryRegister serviceInventoryRegister;
private final CommandService commandService;
private final Gson gson = new Gson();
public ServiceInstancePingServletHandler(ModuleManager moduleManager) {
this.serviceInstanceInventoryRegister = moduleManager.find(CoreModule.NAME).provider().getService(
IServiceInstanceInventoryRegister.class);
this.serviceInstanceInventoryCache = moduleManager.find(CoreModule.NAME).provider().getService(
ServiceInstanceInventoryCache.class);
this.serviceInventoryRegister = moduleManager.find(CoreModule.NAME).provider().getService(
IServiceInventoryRegister.class);
this.commandService = moduleManager.find(CoreModule.NAME).provider().getService(CommandService.class);
}
@Override
public String pathSpec() {
return "/v2/instance/heartbeat";
}
@Override
protected JsonElement doGet(HttpServletRequest req) throws ArgumentsParseException {
throw new UnsupportedOperationException();
}
@Override
protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException {
JsonObject responseJson = new JsonObject();
try {
ServiceInstancePingPkg.Builder builder = ServiceInstancePingPkg.newBuilder();
ProtoBufJsonUtils.fromJSON(getJsonBody(req), builder);
ServiceInstancePingPkg instancePingPkg = builder.build();
int serviceInstanceId = instancePingPkg.getServiceInstanceId();
long heartBeatTime = instancePingPkg.getTime();
String serviceInstanceUUID = instancePingPkg.getServiceInstanceUUID();
serviceInstanceInventoryRegister.heartbeat(serviceInstanceId, heartBeatTime);
ServiceInstanceInventory serviceInstanceInventory = serviceInstanceInventoryCache.get(serviceInstanceId);
if (Objects.nonNull(serviceInstanceInventory)) {
serviceInventoryRegister.heartbeat(serviceInstanceInventory.getServiceId(), heartBeatTime);
} else {
logger.warn(
"Can't found service by service instance id from cache, service instance id is: {}",
serviceInstanceId
);
final ServiceResetCommand resetCommand = commandService.newResetCommand(
serviceInstanceId, heartBeatTime, serviceInstanceUUID);
final Command command = resetCommand.serialize().build();
final Commands nextCommands = Commands.newBuilder().addCommands(command).build();
return gson.fromJson(ProtoBufJsonUtils.toJSON(nextCommands), JsonElement.class);
}
} catch (IOException e) {
responseJson.addProperty("error", e.getMessage());
logger.error(e.getMessage(), e);
}
return responseJson;
}
}
/*
* 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.register.provider.handler.v6.rest;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.skywalking.apm.network.common.KeyStringValuePair;
import org.apache.skywalking.apm.network.register.v2.ServiceInstance;
import org.apache.skywalking.apm.network.register.v2.ServiceInstances;
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.ServiceInstanceInventory;
import org.apache.skywalking.oap.server.core.register.ServiceInventory;
import org.apache.skywalking.oap.server.core.register.service.IServiceInstanceInventoryRegister;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.server.jetty.ArgumentsParseException;
import org.apache.skywalking.oap.server.library.server.jetty.JettyJsonHandler;
import org.apache.skywalking.oap.server.library.util.ProtoBufJsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.skywalking.oap.server.core.register.ServiceInstanceInventory.PropertyUtil.HOST_NAME;
import static org.apache.skywalking.oap.server.core.register.ServiceInstanceInventory.PropertyUtil.IPV4S;
import static org.apache.skywalking.oap.server.core.register.ServiceInstanceInventory.PropertyUtil.LANGUAGE;
import static org.apache.skywalking.oap.server.core.register.ServiceInstanceInventory.PropertyUtil.OS_NAME;
import static org.apache.skywalking.oap.server.core.register.ServiceInstanceInventory.PropertyUtil.PROCESS_NO;
public class ServiceInstanceRegisterServletHandler extends JettyJsonHandler {
private static final Logger logger = LoggerFactory.getLogger(ServiceInstanceRegisterServletHandler.class);
private static final String INSTANCE_CUSTOMIZED_NAME_PREFIX = "NAME:";
private final IServiceInstanceInventoryRegister serviceInstanceInventoryRegister;
private final ServiceInventoryCache serviceInventoryCache;
private static final String KEY = "key";
private static final String VALUE = "value";
public ServiceInstanceRegisterServletHandler(ModuleManager moduleManager) {
this.serviceInventoryCache = moduleManager.find(CoreModule.NAME)
.provider()
.getService(ServiceInventoryCache.class);
this.serviceInstanceInventoryRegister = moduleManager.find(CoreModule.NAME).provider().getService(
IServiceInstanceInventoryRegister.class);
}
@Override
public String pathSpec() {
return "/v2/instance/register";
}
@Override
protected JsonElement doGet(HttpServletRequest req) throws ArgumentsParseException {
throw new UnsupportedOperationException();
}
@Override
protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException {
JsonObject responseJson = new JsonObject();
JsonArray jsonArray = new JsonArray();
try {
ServiceInstances.Builder builder = ServiceInstances.newBuilder();
ProtoBufJsonUtils.fromJSON(getJsonBody(req), builder);
List<ServiceInstance> serviceInstances = builder.build().getInstancesList();
serviceInstances.forEach(instance -> {
long time = instance.getTime();
int serviceId = instance.getServiceId();
String instanceUUID = instance.getInstanceUUID();
JsonObject instanceProperties = new JsonObject();
List<String> ipv4s = new ArrayList<>();
for (KeyStringValuePair property : instance.getPropertiesList()) {
String key = property.getKey();
switch (key) {
case HOST_NAME:
instanceProperties.addProperty(HOST_NAME, property.getValue());
break;
case OS_NAME:
instanceProperties.addProperty(OS_NAME, property.getValue());
break;
case LANGUAGE:
instanceProperties.addProperty(LANGUAGE, property.getValue());
break;
case "ipv4":
ipv4s.add(property.getValue());
break;
case PROCESS_NO:
instanceProperties.addProperty(PROCESS_NO, property.getValue());
break;
default:
instanceProperties.addProperty(key, property.getValue());
}
}
instanceProperties.addProperty(IPV4S, ServiceInstanceInventory.PropertyUtil.ipv4sSerialize(ipv4s));
String instanceName = null;
if (instanceUUID.startsWith(INSTANCE_CUSTOMIZED_NAME_PREFIX)) {
instanceName = instanceUUID.substring(INSTANCE_CUSTOMIZED_NAME_PREFIX.length());
}
ServiceInventory serviceInventory = serviceInventoryCache.get(serviceId);
if (instanceName == null) {
instanceName = serviceInventory.getName();
if (instanceProperties.has(PROCESS_NO)) {
instanceName += "-pid:" + instanceProperties.get(PROCESS_NO).getAsString();
}
if (instanceProperties.has(HOST_NAME)) {
instanceName += "@" + instanceProperties.get(HOST_NAME).getAsString();
}
}
int instanceId = serviceInstanceInventoryRegister.getOrCreate(
serviceId, instanceName, instanceUUID, time, instanceProperties);
responseJson.addProperty(KEY, instanceUUID);
responseJson.addProperty(VALUE, instanceId);
jsonArray.add(responseJson);
});
return jsonArray;
} catch (IOException e) {
responseJson.addProperty("error", e.getMessage());
logger.error(e.getMessage(), e);
}
return responseJson;
}
}
/*
* 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.register.provider.handler.v6.rest;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.skywalking.apm.network.register.v2.Service;
import org.apache.skywalking.apm.network.register.v2.Services;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.register.NodeType;
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.library.server.jetty.ArgumentsParseException;
import org.apache.skywalking.oap.server.library.server.jetty.JettyJsonHandler;
import org.apache.skywalking.oap.server.library.util.ProtoBufJsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ServiceRegisterServletHandler extends JettyJsonHandler {
private static final Logger logger = LoggerFactory.getLogger(ServiceRegisterServletHandler.class);
private final IServiceInventoryRegister serviceInventoryRegister;
private static final String KEY = "key";
private static final String VALUE = "value";
public ServiceRegisterServletHandler(ModuleManager moduleManager) {
serviceInventoryRegister = moduleManager.find(CoreModule.NAME)
.provider()
.getService(IServiceInventoryRegister.class);
}
@Override
public String pathSpec() {
return "/v2/service/register";
}
@Override
protected JsonElement doGet(HttpServletRequest req) throws ArgumentsParseException {
throw new UnsupportedOperationException();
}
@Override
protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException {
JsonArray responseArray = new JsonArray();
try {
Services.Builder builder = Services.newBuilder();
ProtoBufJsonUtils.fromJSON(getJsonBody(req), builder);
List<Service> serviceList = builder.build().getServicesList();
serviceList.forEach(service -> {
int serviceId = serviceInventoryRegister.getOrCreate(service.getServiceName(),
NodeType.fromRegisterServiceType(
service.getType()), null
);
JsonObject mapping = new JsonObject();
mapping.addProperty(KEY, service.getServiceName());
mapping.addProperty(VALUE, serviceId);
responseArray.add(mapping);
});
} catch (IOException e) {
JsonObject mapping = new JsonObject();
mapping.addProperty("error", e.getMessage());
responseArray.add(mapping);
logger.error(e.getMessage(), e);
}
return responseArray;
}
}
......@@ -18,10 +18,12 @@
package org.apache.skywalking.oap.server.receiver.trace.provider;
import java.io.IOException;
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.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;
......@@ -30,6 +32,7 @@ import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedExcepti
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.v6.grpc.TraceSegmentReportServiceHandler;
import org.apache.skywalking.oap.server.receiver.trace.provider.handler.v6.rest.TraceSegmentCollectServletHandler;
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.ISegmentParserService;
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.SegmentParseV2;
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.SegmentParserListenerManager;
......@@ -41,8 +44,6 @@ import org.apache.skywalking.oap.server.receiver.trace.provider.parser.listener.
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.standardization.SegmentStandardizationWorker;
import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
import java.io.IOException;
public class TraceModuleProvider extends ModuleProvider {
private final TraceServiceModuleConfig moduleConfig;
......@@ -80,7 +81,8 @@ public class TraceModuleProvider extends ModuleProvider {
segmentProducerV2 = new SegmentParseV2.Producer(getManager(), listenerManager(), moduleConfig);
this.registerServiceImplementation(ISegmentParserService.class, new SegmentParserServiceImpl(segmentProducerV2));
this.registerServiceImplementation(
ISegmentParserService.class, new SegmentParserServiceImpl(segmentProducerV2));
}
public SegmentParserListenerManager listenerManager() {
......@@ -99,19 +101,28 @@ public class TraceModuleProvider extends ModuleProvider {
public void start() throws ModuleStartException {
DynamicConfigurationService dynamicConfigurationService = getManager().find(ConfigurationModule.NAME)
.provider()
.getService(DynamicConfigurationService.class);
.getService(
DynamicConfigurationService.class);
GRPCHandlerRegister grpcHandlerRegister = getManager().find(SharingServerModule.NAME)
.provider()
.getService(GRPCHandlerRegister.class);
JettyHandlerRegister jettyHandlerRegister = getManager().find(SharingServerModule.NAME)
.provider()
.getService(JettyHandlerRegister.class);
try {
dynamicConfigurationService.registerConfigChangeWatcher(thresholds);
dynamicConfigurationService.registerConfigChangeWatcher(uninstrumentedGatewaysConfig);
grpcHandlerRegister.addHandler(new TraceSegmentReportServiceHandler(segmentProducerV2, getManager()));
SegmentStandardizationWorker standardizationWorkerV2 = new SegmentStandardizationWorker(getManager(), segmentProducerV2, moduleConfig
.getBufferPath(), moduleConfig.getBufferOffsetMaxFileSize(), moduleConfig.getBufferDataMaxFileSize(), moduleConfig
.isBufferFileCleanWhenRestart());
jettyHandlerRegister.addHandler(new TraceSegmentCollectServletHandler(segmentProducerV2));
SegmentStandardizationWorker standardizationWorkerV2 = new SegmentStandardizationWorker(
getManager(), segmentProducerV2, moduleConfig
.getBufferPath(), moduleConfig.getBufferOffsetMaxFileSize(), moduleConfig.getBufferDataMaxFileSize(),
moduleConfig
.isBufferFileCleanWhenRestart()
);
segmentProducerV2.setStandardizationWorker(standardizationWorkerV2);
} catch (IOException e) {
throw new ModuleStartException(e.getMessage(), e);
......
/*
* 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.handler.v6.rest;
import com.google.gson.JsonElement;
import java.io.BufferedReader;
import javax.servlet.http.HttpServletRequest;
import org.apache.skywalking.apm.network.language.agent.UpstreamSegment;
import org.apache.skywalking.oap.server.library.server.jetty.JettyJsonHandler;
import org.apache.skywalking.oap.server.receiver.trace.provider.handler.v6.rest.reader.UpstreamSegmentJsonReader;
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.SegmentParseV2;
import org.apache.skywalking.oap.server.receiver.trace.provider.parser.SegmentSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TraceSegmentCollectServletHandler extends JettyJsonHandler {
private static final Logger logger = LoggerFactory.getLogger(TraceSegmentCollectServletHandler.class);
private final SegmentParseV2.Producer segmentProducer;
private UpstreamSegmentJsonReader upstreamSegmentJsonReader = new UpstreamSegmentJsonReader();
public TraceSegmentCollectServletHandler(SegmentParseV2.Producer segmentProducer) {
this.segmentProducer = segmentProducer;
}
@Override
public String pathSpec() {
return "/v2/segments";
}
@Override
protected JsonElement doGet(HttpServletRequest req) {
throw new UnsupportedOperationException();
}
@Override
protected JsonElement doPost(HttpServletRequest req) {
if (logger.isDebugEnabled()) {
logger.debug("receive stream segment");
}
StringBuilder stringBuilder = new StringBuilder();
String line = null;
try {
BufferedReader reader = req.getReader();
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
UpstreamSegment upstreamSegment = upstreamSegmentJsonReader.read(stringBuilder.toString()).build();
segmentProducer.send(upstreamSegment, SegmentSource.Agent);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}
}
/*
* 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.handler.v6.rest.reader;
import java.io.IOException;
import org.apache.skywalking.apm.network.language.agent.v2.SegmentObject;
import org.apache.skywalking.oap.server.library.util.ProtoBufJsonUtils;
public class SegmentJsonReader implements StreamJsonReader<SegmentObject.Builder> {
@Override
public SegmentObject.Builder read(String json) throws IOException {
SegmentObject.Builder builder = SegmentObject.newBuilder();
ProtoBufJsonUtils.fromJSON(json, builder);
return builder;
}
}
/*
* 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.handler.v6.rest.reader;
import java.io.IOException;
public interface StreamJsonReader<T> {
T read(String json) throws IOException;
}
/*
* 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.handler.v6.rest.reader;
import java.io.IOException;
import org.apache.skywalking.apm.network.language.agent.UpstreamSegment;
import org.apache.skywalking.apm.network.language.agent.v2.SegmentObject;
import org.apache.skywalking.oap.server.library.util.ProtoBufJsonUtils;
public class UpstreamSegmentJsonReader implements StreamJsonReader<UpstreamSegment.Builder> {
private final SegmentJsonReader segmentJsonReader = new SegmentJsonReader();
@Override
public UpstreamSegment.Builder read(String json) throws IOException {
UpstreamSegment.Builder upstreamSegmentBuilder = UpstreamSegment.newBuilder();
ProtoBufJsonUtils.fromJSON(json, upstreamSegmentBuilder);
SegmentObject.Builder segmentBuilder = segmentJsonReader.read(json);
upstreamSegmentBuilder.setSegment(segmentBuilder.build().toByteString());
return upstreamSegmentBuilder;
}
}
/*
* 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.parser.listener.segment;
import java.io.IOException;
import org.apache.skywalking.apm.network.common.Command;
import org.apache.skywalking.apm.network.common.Commands;
import org.apache.skywalking.apm.network.language.agent.UpstreamSegment;
import org.apache.skywalking.apm.network.language.agent.v2.SegmentObject;
import org.apache.skywalking.oap.server.library.util.ProtoBufJsonUtils;
import org.junit.Assert;
import org.junit.Test;
public class ProtoBufJsonUtilsTest {
@Test
public void testProtoBuf() {
String json = "{\n" +
" \"spans\": [\n" +
" {\n" +
" \"operationName\": \"/tier2/lb\",\n" +
" \"startTime\": 1582526028207,\n" +
" \"endTime\": 1582526028221,\n" +
" \"spanType\": \"Exit\",\n" +
" \"spanId\": 1,\n" +
" \"isError\": false,\n" +
" \"parentSpanId\": 0,\n" +
" \"componentId\": 6000,\n" +
" \"peer\": \"User Service Name-nginx:upstream_ip:port\",\n" +
" \"spanLayer\": \"HTTP\"\n" +
" },\n" +
" {\n" +
" \"operationName\": \"/tier2/lb\",\n" +
" \"startTime\": 1582526028207,\n" +
" \"tags\": [\n" +
" {\n" +
" \"key\": \"http.method\",\n" +
" \"value\": \"GET\"\n" +
" },\n" +
" {\n" +
" \"key\": \"http.params\",\n" +
" \"value\": \"http://127.0.0.1/tier2/lb\"\n" +
" }\n" +
" ],\n" +
" \"endTime\": 1582526028221,\n" +
" \"spanType\": \"Entry\",\n" +
" \"spanId\": 0,\n" +
" \"isError\": false,\n" +
" \"parentSpanId\": -1,\n" +
" \"componentId\": 6000,\n" +
" \"refs\": [\n" +
" {\n" +
" \"parentTraceSegmentId\": {\n" +
" \"idParts\": [\n" +
" 1582526028032,\n" +
" 794206293,\n" +
" 69887\n" +
" ]\n" +
" },\n" +
" \"parentEndpointId\": 0,\n" +
" \"entryEndpointId\": 0,\n" +
" \"parentServiceInstanceId\": 1,\n" +
" \"parentEndpoint\": \"/ingress\",\n" +
" \"networkAddress\": \"#User Service Name-nginx:upstream_ip:port\",\n" +
" \"parentSpanId\": 1,\n" +
" \"entryServiceInstanceId\": 1,\n" +
" \"networkAddressId\": 0,\n" +
" \"entryEndpoint\": \"/ingress\"\n" +
" }\n" +
" ],\n" +
" \"spanLayer\": \"HTTP\"\n" +
" }\n" +
" ],\n" +
" \"serviceInstanceId\": 1,\n" +
" \"serviceId\": 1,\n" +
" \"traceSegmentId\": {\n" +
" \"idParts\": [\n" +
" 1582526028040,\n" +
" 794206293,\n" +
" 69887\n" +
" ]\n" +
" },\n" +
" \"globalTraceIds\": [\n" +
" {\n" +
" \"idParts\": [\n" +
" 1582526028032,\n" +
" 794206293,\n" +
" 69887\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}";
UpstreamSegment.Builder builder = UpstreamSegment.newBuilder();
try {
ProtoBufJsonUtils.fromJSON(json, builder);
UpstreamSegment upstreamSegment = builder.build();
Assert.assertEquals(1582526028032L, upstreamSegment.getGlobalTraceIds(0).getIdParts(0));
SegmentObject.Builder segBuilder = SegmentObject.newBuilder();
ProtoBufJsonUtils.fromJSON(json, segBuilder);
SegmentObject segmentObject = segBuilder.build();
Assert.assertEquals(2, segmentObject.getSpansCount());
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testToJson() {
String json = "{\n" +
" \"commands\": [{\n" +
" }]\n" +
"}";
try {
Command command = Command.newBuilder().build();
final Commands nextCommands = Commands.newBuilder().addCommands(command).build();
Assert.assertEquals(json, ProtoBufJsonUtils.toJSON(nextCommands));
} catch (IOException e) {
e.printStackTrace();
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>apache-skywalking-e2e</artifactId>
<groupId>org.apache.skywalking</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>e2e-http-api-with-nginx-lua</artifactId>
<properties>
<e2e.container.version>1.1</e2e.container.version>
<e2e.container.name.prefix>skywalking-e2e-container-${build.id}-http-api-with-nginx-lua
</e2e.container.name.prefix>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>e2e-base</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<configuration>
<executable>true</executable>
<addResources>true</addResources>
<excludeDevtools>true</excludeDevtools>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<containerNamePattern>%a-%t-%i</containerNamePattern>
<images>
<image>
<name>skyapm/e2e-container:${e2e.container.version}</name>
<alias>e2e-container-app-for-nginx-lua</alias>
<run>
<env>
<INSTRUMENTED_SERVICE>${project.build.finalName}.jar</INSTRUMENTED_SERVICE>
<INSTRUMENTED_SERVICE_OPTS>-Dskywalking.agent.cool_down_threshold=1
</INSTRUMENTED_SERVICE_OPTS>
</env>
<ports>
<port>+webapp.host:webapp.port:8080</port>
<port>+client.host:client.port:9090</port>
</ports>
<volumes>
<bind>
<volume>${sw.home}:/sw</volume>
<volume>${project.build.directory}:/home</volume>
<volume>
${project.basedir}/src/docker/rc.d/rc1-startup.sh:/rc.d/rc1-startup.sh:ro
</volume>
</bind>
</volumes>
<wait>
<http>
<url>
http://${docker.host.address}:${client.port}/e2e/info
</url>
<method>GET</method>
<status>200</status>
</http>
<time>300000</time>
</wait>
</run>
</image>
<image>
<name>openresty/openresty</name>
<alias>${e2e.container.name.prefix}-openresty</alias>
<run>
<env>
<SKYWALKING_NINGX_LUA_GIT_COMMIT_ID>c6aca516200573a64db7060cefb5d3608c571c3a
</SKYWALKING_NINGX_LUA_GIT_COMMIT_ID>
</env>
<links>
<link>e2e-container-app-for-nginx-lua:upstream</link>
</links>
<ports>
<port>+nginx.host:nginx.port:8080</port>
</ports>
<volumes>
<bind>
<volume>${project.basedir}/src/docker/rc.d:/rc.d:ro</volume>
</bind>
</volumes>
<wait>
<http>
<url>
http://${docker.host.address}:${nginx.port}
</url>
</http>
<time>3000000</time>
</wait>
<cmd>/rc.d/rc0-prepare.sh</cmd>
</run>
</image>
</images>
</configuration>
</plugin>
<!-- set the system properties that can be used in test codes -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<sw.webapp.host>
${webapp.host}
</sw.webapp.host>
<sw.webapp.port>
${webapp.port}
</sw.webapp.port>
<client.host>
${client.host}
</client.host>
<client.port>
${client.port}
</client.port>
<nginx.port>
${nginx.port}
</nginx.port>
</systemPropertyVariables>
</configuration>
<executions>
<execution>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<ping.url>
http://${nginx.host}:${nginx.port}/ingress
</ping.url>
</systemPropertyVariables>
</configuration>
<executions>
<execution>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
#!/usr/bin/env bash
# Licensed to the SkyAPM 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.
#!/bin/bash
set -e
var_application_file="/var/nginx/conf.d/nginx.conf"
var_upstream_ip=$(cat /etc/hosts|grep upstream|awk '{print $1'})
apt-get update && apt-get -y install git
echo 'git clone skyalking-nginx-lua lib from https://github.com/apache/skywalking-nginx-lua.git'
git clone https://github.com/apache/skywalking-nginx-lua.git /usr/share/skywalking-nginx-lua \
&& cd /usr/share/skywalking-nginx-lua \
&& git checkout ${SKYWALKING_NINGX_LUA_GIT_COMMIT_ID} \
&& ls ./ \
&& mkdir -p /var/nginx/conf.d
generateNginxConf() {
cat <<EOT >> ${var_application_file}
worker_processes 1;
daemon off;
error_log /dev/stdout error;
events {
worker_connections 1024;
}
http {
lua_package_path "/usr/share/skywalking-nginx-lua/lib/skywalking/?.lua;;";
# Buffer represents the register inform and the queue of the finished segment
lua_shared_dict tracing_buffer 100m;
# Init is the timer setter and keeper
# Setup an infinite loop timer to do register and trace report.
init_worker_by_lua_block {
local metadata_buffer = ngx.shared.tracing_buffer
metadata_buffer:set('serviceName', 'User_Service_Name')
-- Instance means the number of Nginx deloyment, does not mean the worker instances
metadata_buffer:set('serviceInstanceName', 'User_Service_Instance_Name')
require("client"):startBackendTimer("http://${var_upstream_ip}:12800")
}
log_format sw_trace escape=json "$uri $request_body";
server {
listen 8080;
location /nginx/e2e/info {
rewrite_by_lua_block {
require("tracer"):start("User_Service_Name")
}
proxy_pass http://upstream:9090/e2e/info;
body_filter_by_lua_block {
require("tracer"):finish()
}
log_by_lua_block {
require("tracer"):prepareForReport()
}
}
}
}
EOT
}
generateNginxConf;
echo 'generated nginx.conf:'
cat ${var_application_file}
/usr/bin/openresty -c ${var_application_file}
sync
#!/usr/bin/env bash
# Licensed to the SkyAPM 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.
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'
echo 'starting Web app...' \
&& start_webapp '0.0.0.0' 8080
echo 'starting instrumented services...' \
&& start_instrumented_services
check_tcp 127.0.0.1 \
9090 \
60 \
10 \
"waiting for the instrumented service to be ready"
if [[ $? -ne 0 ]]; then
echo "instrumented service failed to start in 30 * 10 seconds: "
cat ${SERVICE_LOG}/*
exit 1
fi
echo "SkyWalking e2e container is ready for tests"
tail -f ${OAP_LOG_DIR}/* \
${WEBAPP_LOG_DIR}/* \
${SERVICE_LOG}/* \
${ES_HOME}/logs/stdout.log
/*
* 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.sample.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SampleClientApplication {
public static void main(String[] args) {
SpringApplication.run(SampleClientApplication.class, args);
}
}
/*
* 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.sample.client;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/e2e")
public class TestController {
@GetMapping("/info")
public String hello() {
return "e2e-container-info";
}
}
# 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: 9090
spring:
main:
banner-mode: 'off'
/*
* 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.io.InputStream;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.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.ServiceInstanceTopoData;
import org.apache.skywalking.e2e.topo.ServiceInstanceTopoMatcher;
import org.apache.skywalking.e2e.topo.ServiceInstanceTopoQuery;
import org.apache.skywalking.e2e.topo.TopoData;
import org.apache.skywalking.e2e.topo.TopoMatcher;
import org.apache.skywalking.e2e.topo.TopoQuery;
import org.apache.skywalking.e2e.trace.Trace;
import org.apache.skywalking.e2e.trace.TracesMatcher;
import org.apache.skywalking.e2e.trace.TracesQuery;
import org.junit.Before;
import org.junit.Test;
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;
import org.springframework.web.client.RestTemplate;
import org.yaml.snakeyaml.Yaml;
import static org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyMetrics;
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_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_RELATION_CLIENT_METRICS;
import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_SERVER_METRICS;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringJUnit4ClassRunner.class)
public class SampleVerificationITCase {
private static final Logger LOGGER = LoggerFactory.getLogger(SampleVerificationITCase.class);
private final RestTemplate restTemplate = new RestTemplate();
private final int retryInterval = 30;
private SimpleQueryClient queryClient;
private String nginxServiceUrl;
@Before
public void setUp() {
final String swWebappHost = System.getProperty("sw.webapp.host", "127.0.0.1");
final String swWebappPort = System.getProperty("sw.webapp.port", "32783");
final String nginxHost = System.getProperty("nginx.host", "127.0.0.1");
final String nginxPort = System.getProperty("nginx.port", "32782");
queryClient = new SimpleQueryClient(swWebappHost, swWebappPort);
nginxServiceUrl = "http://" + nginxHost + ":" + nginxPort;
}
@Test(timeout = 1200000)
@DirtiesContext
public void verify() throws Exception {
final LocalDateTime minutesAgo = LocalDateTime.now(ZoneOffset.UTC);
while (true) {
final List<Service> services = queryClient.services(
new ServicesQuery().start(minutesAgo).end(LocalDateTime.now()));
if (!services.isEmpty() && services.size() >= 2) {
break;
}
Thread.sleep(10000L);
}
while (true) {
try {
final Map<String, String> user = new HashMap<>();
user.put("name", "SkyWalking");
final ResponseEntity<String> responseEntity = restTemplate.getForEntity(
nginxServiceUrl + "/nginx/e2e/info", String.class);
LOGGER.info("responseEntity: {}", responseEntity);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(responseEntity.getBody()).isEqualTo("e2e-container-info");
final List<Trace> traces = queryClient.traces(new TracesQuery().start(minutesAgo)
.end(LocalDateTime.now())
.orderByDuration());
if (!traces.isEmpty() && traces.size() >= 2) {
break;
}
Thread.sleep(10000L);
} catch (Exception ignored) {
}
}
doRetryableVerification(() -> {
try {
verifyTraces(minutesAgo);
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
}
});
doRetryableVerification(() -> {
try {
verifyServices(minutesAgo);
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
}
});
doRetryableVerification(() -> {
try {
verifyTopo(minutesAgo);
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
}
});
doRetryableVerification(() -> {
try {
verifyServiceInstanceTopo(minutesAgo);
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
}
});
}
private void verifyTopo(LocalDateTime minutesAgo) throws Exception {
final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
final TopoData topoData = queryClient.topo(new TopoQuery().stepByMinute()
.start(minutesAgo.minusDays(1))
.end(now));
LOGGER.info("topoData: {}", topoData);
InputStream expectedInputStream = new ClassPathResource(
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.topo.yml")
.getInputStream();
final TopoMatcher topoMatcher = new Yaml().loadAs(expectedInputStream, TopoMatcher.class);
topoMatcher.verify(topoData);
verifyServiceRelationMetrics(topoData.getCalls(), minutesAgo);
}
private void verifyServiceInstanceTopo(LocalDateTime minutesAgo) throws Exception {
final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
final ServiceInstanceTopoData topoData = queryClient.serviceInstanceTopo(
new ServiceInstanceTopoQuery().stepByMinute()
.start(minutesAgo
.minusDays(1))
.end(now)
.clientServiceId("1")
.serverServiceId("3"));
LOGGER.info("instanceTopoData: {}", topoData);
InputStream expectedInputStream = new ClassPathResource(
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.serviceInstanceTopo.yml")
.getInputStream();
final ServiceInstanceTopoMatcher topoMatcher = new Yaml().loadAs(
expectedInputStream, ServiceInstanceTopoMatcher.class);
topoMatcher.verify(topoData);
verifyServiceInstanceRelationMetrics(topoData.getCalls(), minutesAgo);
}
private void verifyServices(LocalDateTime minutesAgo) throws Exception {
final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
final List<Service> services = queryClient.services(new ServicesQuery().start(minutesAgo).end(now));
LOGGER.info("services: {}", services);
InputStream expectedInputStream = new ClassPathResource(
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.services.yml")
.getInputStream();
final ServicesMatcher servicesMatcher = new Yaml().loadAs(expectedInputStream, ServicesMatcher.class);
servicesMatcher.verify(services);
for (Service service : services) {
LOGGER.info("verifying service instances: {}", service);
verifyServiceMetrics(service);
Instances instances = verifyServiceInstances(minutesAgo, now, service);
verifyInstancesMetrics(instances);
Endpoints endpoints = verifyServiceEndpoints(minutesAgo, now, service);
verifyEndpointsMetrics(endpoints);
}
}
private Instances verifyServiceInstances(LocalDateTime minutesAgo, LocalDateTime now,
Service service) throws Exception {
Instances instances = queryClient.instances(new InstancesQuery().serviceId(service.getKey())
.start(minutesAgo)
.end(now));
LOGGER.info("instances: {}", instances);
InputStream expectedInputStream;
if ("User_Service_Name".equals(service.getLabel())) {
expectedInputStream = new ClassPathResource(
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.nginxInstances.yml")
.getInputStream();
} else {
expectedInputStream = new ClassPathResource(
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.instances.yml")
.getInputStream();
}
final InstancesMatcher instancesMatcher = new Yaml().loadAs(expectedInputStream, InstancesMatcher.class);
instancesMatcher.verify(instances);
return instances;
}
private Endpoints verifyServiceEndpoints(LocalDateTime minutesAgo, LocalDateTime now,
Service service) throws Exception {
Endpoints endpoints = queryClient.endpoints(new EndpointQuery().serviceId(service.getKey()));
LOGGER.info("instances: {}", endpoints);
InputStream expectedInputStream;
if ("/e2e/health-check".equals(endpoints.getEndpoints().get(0).getLabel())) {
expectedInputStream = new ClassPathResource(
"org.apache.skywalking.e2e.SampleVerificationITCase.nginxEndpoints.yml")
.getInputStream();
} else {
expectedInputStream = new ClassPathResource(
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.endpoints.yml")
.getInputStream();
}
final EndpointsMatcher endpointsMatcher = new Yaml().loadAs(expectedInputStream, EndpointsMatcher.class);
endpointsMatcher.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 = queryClient.metrics(new MetricsQuery().stepByMinute()
.metricsName(metricsName)
.id(instance.getKey()));
LOGGER.info("instanceMetrics: {}", instanceMetrics);
AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
greaterThanZero.setValue("ge 0");
instanceRespTimeMatcher.setValue(greaterThanZero);
instanceRespTimeMatcher.verify(instanceMetrics);
LOGGER.info("{}: {}", metricsName, instanceMetrics);
}
}
}
private void verifyEndpointsMetrics(Endpoints endpoints) throws Exception {
for (Endpoint endpoint : endpoints.getEndpoints()) {
if (!endpoint.getLabel().equals("/e2e/info") || !endpoint.getLabel()
.equals("/nginx/e2e/info")) {
continue;
}
for (String metricName : ALL_ENDPOINT_METRICS) {
LOGGER.info("verifying endpoint {}, metrics: {}", endpoint, metricName);
final Metrics metrics = queryClient.metrics(new MetricsQuery().stepByMinute()
.metricsName(metricName)
.id(endpoint.getKey()));
LOGGER.info("metrics: {}", metrics);
AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
greaterThanZero.setValue("ge 0");
instanceRespTimeMatcher.setValue(greaterThanZero);
instanceRespTimeMatcher.verify(metrics);
LOGGER.info("{}: {}", metricName, metrics);
}
}
}
private void verifyServiceMetrics(Service service) throws Exception {
for (String metricName : ALL_SERVICE_METRICS) {
LOGGER.info("verifying service {}, metrics: {}", service, metricName);
final Metrics serviceMetrics = queryClient.metrics(new MetricsQuery().stepByMinute()
.metricsName(metricName)
.id(service.getKey()));
LOGGER.info("serviceMetrics: {}", serviceMetrics);
AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
greaterThanZero.setValue("ge 0");
instanceRespTimeMatcher.setValue(greaterThanZero);
instanceRespTimeMatcher.verify(serviceMetrics);
LOGGER.info("{}: {}", metricName, serviceMetrics);
}
}
private void verifyTraces(LocalDateTime minutesAgo) throws Exception {
final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
final List<Trace> traces = queryClient.traces(new TracesQuery().start(minutesAgo).end(now).orderByDuration());
LOGGER.info("traces: {}", traces);
InputStream expectedInputStream = new ClassPathResource(
"expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.traces.yml")
.getInputStream();
final TracesMatcher tracesMatcher = new Yaml().loadAs(expectedInputStream, TracesMatcher.class);
tracesMatcher.verifyLoosely(traces);
}
private void verifyServiceInstanceRelationMetrics(List<Call> calls,
final LocalDateTime minutesAgo) throws Exception {
verifyRelationMetrics(
calls, minutesAgo, ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS,
ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS
);
}
private void verifyServiceRelationMetrics(List<Call> calls, final LocalDateTime minutesAgo) throws Exception {
verifyRelationMetrics(
calls, minutesAgo, ALL_SERVICE_RELATION_CLIENT_METRICS, ALL_SERVICE_RELATION_SERVER_METRICS);
}
private void verifyRelationMetrics(List<Call> calls, final LocalDateTime minutesAgo, String[] relationClientMetrics,
String[] relationServerMetrics) throws Exception {
for (Call call : calls) {
for (String detectPoint : call.getDetectPoints()) {
switch (detectPoint) {
case "CLIENT": {
for (String metricName : relationClientMetrics) {
verifyMetrics(queryClient, metricName, call.getId(), minutesAgo);
}
break;
}
case "SERVER": {
for (String metricName : relationServerMetrics) {
verifyMetrics(queryClient, metricName, call.getId(), minutesAgo);
}
break;
}
}
}
}
}
private void doRetryableVerification(Runnable runnable) throws InterruptedException {
while (true) {
try {
runnable.run();
break;
} catch (Throwable ignored) {
Thread.sleep(retryInterval);
}
}
}
}
# 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.
# 1 health-check by docker-maven-plugin
# 1 drop table if exists, because we have `ddl-auto: create-drop`
# 1 drop sequence
# 1 create sequence
# 1 create table statement
endpoints:
- key: not null
label: /e2e/info
# 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.
# 1 health-check by docker-maven-plugin
# 1 drop table if exists, because we have `ddl-auto: create-drop`
# 1 drop sequence
# 1 create sequence
# 1 create table statement
instances:
- key: 2
label: not null
attributes:
- name: os_name
value: not null
- name: host_name
value: not null
- name: process_no
value: gt 0
- name: ipv4s
value: not null
# 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.
# 1 health-check by docker-maven-plugin
# 1 drop table if exists, because we have `ddl-auto: create-drop`
# 1 drop sequence
# 1 create sequence
# 1 create table statement
nodes:
- id: 1
name: User
type: USER
serviceId: 1
serviceName: User
isReal: false
- id: 3
name: not null
serviceId: 3
serviceName: User_Service_Name
type: not null
isReal: true
calls:
- id: 1_3
source: 1
detectPoints:
- SERVER
target: 3
# 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.
# 1 health-check by docker-maven-plugin
# 1 drop table if exists, because we have `ddl-auto: create-drop`
# 1 drop sequence
# 1 create sequence
# 1 create table statement
services:
- key: 2
label: "Your_ApplicationName"
- key: 3
label: "User_Service_Name"
\ No newline at end of file
# 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.
# 1 health-check by docker-maven-plugin
# 1 drop table if exists, because we have `ddl-auto: create-drop`
# 1 drop sequence
# 1 create sequence
# 1 create table statement
nodes:
- id: 1
name: User
type: USER
isReal: false
- id: 2
name: Your_ApplicationName
type: Tomcat
isReal: true
- id: 3
name: User_Service_Name
type: Nginx
isReal: true
calls:
- id: 1_3
source: 1
detectPoints:
- SERVER
target: 3
- id: 3_2
source: 3
detectPoints:
- CLIENT
- SERVER
target: 2
\ No newline at end of file
# 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.
# 1 health-check by docker-maven-plugin
# 1 drop table if exists, because we have `ddl-auto: create-drop`
# 1 drop sequence
# 1 create sequence
# 1 create table statement
traces:
- key: not null
endpointNames:
- /e2e/info
duration: ge 0
start: gt 0
isError: false
traceIds:
- not null
- key: not null
endpointNames:
- /nginx/e2e/info
duration: ge 0
start: gt 0
isError: false
traceIds:
- not null
\ No newline at end of file
......@@ -44,6 +44,7 @@
<module>e2e-6.x-agent-7.x-oap-compatibility</module>
<module>e2e-profile</module>
<module>e2e-protocol</module>
<module>e2e-http-api-with-nginx-lua</module>
</modules>
<properties>
......
......@@ -142,7 +142,8 @@ opencensus-contrib-grpc-metrics-0.24.0.jar
parent-join-client-7.0.0.jar
perfmark-api-0.19.0.jar
proto-google-common-protos-1.12.0.jar
protobuf-java-3.4.0.jar
protobuf-java-3.11.4.jar
protobuf-java-util-3.11.4.jar
rank-eval-client-7.0.0.jar
reactive-streams-1.0.2.jar
reflectasm-1.11.7.jar
......
......@@ -140,7 +140,8 @@ opencensus-contrib-grpc-metrics-0.24.0.jar
parent-join-client-6.3.2.jar
perfmark-api-0.19.0.jar
proto-google-common-protos-1.12.0.jar
protobuf-java-3.4.0.jar
protobuf-java-3.11.4.jar
protobuf-java-util-3.11.4.jar
rank-eval-client-6.3.2.jar
reactive-streams-1.0.2.jar
reflectasm-1.11.7.jar
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册