diff --git a/README.md b/README.md index cdb892f3fa9517524fe061ed5fb08516f17693e7..5ab9703d74a506405790ca6c51137efce05a8ed2 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,13 @@ Underlying technology is a distributed tracing system. * Pure Java server implementation, provide RESTful and gRPC services. Compatibility with other language agents/SDKs. * The UI released on [skywalking-ui](https://github.com/apache/incubator-skywalking-ui) -# Architecture - - # Document -[![EN doc](https://img.shields.io/badge/document-English-blue.svg)](docs/README.md) [![cn doc](https://img.shields.io/badge/document-中文-blue.svg)](docs/README_ZH.md) +[![EN doc](https://img.shields.io/badge/document-English-blue.svg)](docs/README.md) [![cn doc](https://img.shields.io/badge/文档-中文版-blue.svg)](docs/README_ZH.md) + +# 5.x Architecture + +# Code of conduct This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to wusheng@apache.org. # Screenshots diff --git a/README_ZH.md b/README_ZH.md index 5e60fb898bea798708c22b35181786052b72a437..e6c31b836e7cc27f3eb7aa753089a8a1fe77be40 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -24,12 +24,14 @@ Apache SkyWalking | [English](README.md) * UI工程请查看 [skywalking-ui](https://github.com/apache/incubator-skywalking-ui) * 中文QQ群:392443393 -# Architecture - - # Document -[![EN doc](https://img.shields.io/badge/document-English-blue.svg)](docs/README.md) [![cn doc](https://img.shields.io/badge/document-中文-blue.svg)](docs/README_ZH.md) +[![EN doc](https://img.shields.io/badge/document-English-blue.svg)](docs/README.md) [![cn doc](https://img.shields.io/badge/文档-中文版-blue.svg)](docs/README_ZH.md) + + +# 5.x Architecture + +# code of conduct This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to wusheng@apache.org. # Screenshots diff --git a/apm-collector/apm-collector-agent/agent-grpc/agent-grpc-provider/src/main/java/org/apache/skywalking/apm/collector/agent/grpc/provider/handler/InstanceDiscoveryServiceHandler.java b/apm-collector/apm-collector-agent/agent-grpc/agent-grpc-provider/src/main/java/org/apache/skywalking/apm/collector/agent/grpc/provider/handler/InstanceDiscoveryServiceHandler.java index 38f174ef3271af51eb34b93609c4211aff4eac42..0841ac3145bda6c6b8c7eaf1c1bf782fe2006d79 100644 --- a/apm-collector/apm-collector-agent/agent-grpc/agent-grpc-provider/src/main/java/org/apache/skywalking/apm/collector/agent/grpc/provider/handler/InstanceDiscoveryServiceHandler.java +++ b/apm-collector/apm-collector-agent/agent-grpc/agent-grpc-provider/src/main/java/org/apache/skywalking/apm/collector/agent/grpc/provider/handler/InstanceDiscoveryServiceHandler.java @@ -28,8 +28,6 @@ import org.apache.skywalking.apm.collector.core.util.TimeBucketUtils; import org.apache.skywalking.apm.collector.server.grpc.GRPCHandler; import org.apache.skywalking.apm.network.proto.ApplicationInstance; import org.apache.skywalking.apm.network.proto.ApplicationInstanceMapping; -import org.apache.skywalking.apm.network.proto.ApplicationInstanceRecover; -import org.apache.skywalking.apm.network.proto.Downstream; import org.apache.skywalking.apm.network.proto.InstanceDiscoveryServiceGrpc; import org.apache.skywalking.apm.network.proto.OSInfo; import org.slf4j.Logger; @@ -59,14 +57,6 @@ public class InstanceDiscoveryServiceHandler extends InstanceDiscoveryServiceGrp responseObserver.onCompleted(); } - @Override - public void registerRecover(ApplicationInstanceRecover request, StreamObserver responseObserver) { - long timeBucket = TimeBucketUtils.INSTANCE.getSecondTimeBucket(request.getRegisterTime()); - instanceIDService.recover(request.getApplicationInstanceId(), request.getApplicationId(), timeBucket, buildOsInfo(request.getOsinfo())); - responseObserver.onNext(Downstream.newBuilder().build()); - responseObserver.onCompleted(); - } - private String buildOsInfo(OSInfo osinfo) { JsonObject osInfoJson = new JsonObject(); osInfoJson.addProperty("osName", osinfo.getOsName()); diff --git a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/BlockingDataCarrier.java b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/BlockingDataCarrier.java new file mode 100644 index 0000000000000000000000000000000000000000..8b970808d3d11a3bfaa2457044dcd2050aeec94d --- /dev/null +++ b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/BlockingDataCarrier.java @@ -0,0 +1,37 @@ +/* + * 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.apm.commons.datacarrier; + +import org.apache.skywalking.apm.commons.datacarrier.buffer.Channels; +import org.apache.skywalking.apm.commons.datacarrier.callback.QueueBlockingCallback; + +/** + * @author wu-sheng + */ +public class BlockingDataCarrier { + private Channels channels; + + BlockingDataCarrier(Channels channels) { + this.channels = channels; + } + + public void addCallback(QueueBlockingCallback callback) { + this.channels.addCallback(callback); + } +} diff --git a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/DataCarrier.java b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/DataCarrier.java index d40c1da82fe00deff75402dd6728717e32a639db..081b25a6f33e44247a4d562af24671446ac5784d 100644 --- a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/DataCarrier.java +++ b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/DataCarrier.java @@ -16,21 +16,17 @@ * */ - package org.apache.skywalking.apm.commons.datacarrier; -import org.apache.skywalking.apm.commons.datacarrier.buffer.Channels; -import org.apache.skywalking.apm.commons.datacarrier.partition.IDataPartitioner; import org.apache.skywalking.apm.commons.datacarrier.buffer.BufferStrategy; +import org.apache.skywalking.apm.commons.datacarrier.buffer.Channels; import org.apache.skywalking.apm.commons.datacarrier.consumer.ConsumerPool; import org.apache.skywalking.apm.commons.datacarrier.consumer.IConsumer; +import org.apache.skywalking.apm.commons.datacarrier.partition.IDataPartitioner; import org.apache.skywalking.apm.commons.datacarrier.partition.SimpleRollingPartitioner; /** - * DataCarrier main class. - * use this instance to set Producer/Consumer Model - *

- * Created by wusheng on 2016/10/25. + * DataCarrier main class. use this instance to set Producer/Consumer Model. */ public class DataCarrier { private final int bufferSize; @@ -45,8 +41,8 @@ public class DataCarrier { } /** - * set a new IDataPartitioner. - * It will cover the current one or default one.(Default is {@link SimpleRollingPartitioner)} + * set a new IDataPartitioner. It will cover the current one or default one.(Default is {@link + * SimpleRollingPartitioner)} * * @param dataPartitioner * @return @@ -57,8 +53,7 @@ public class DataCarrier { } /** - * override the strategy at runtime. - * Notice, {@link Channels} will override several channels one by one. + * override the strategy at runtime. Notice, {@link Channels} will override several channels one by one. * * @param strategy */ @@ -67,6 +62,11 @@ public class DataCarrier { return this; } + public BlockingDataCarrier toBlockingDataCarrier() { + this.channels.setStrategy(BufferStrategy.BLOCKING); + return new BlockingDataCarrier(this.channels); + } + /** * produce data to buffer, using the givven {@link BufferStrategy}. * @@ -84,38 +84,59 @@ public class DataCarrier { } /** - * set consumers to this Carrier. - * consumer begin to run when {@link DataCarrier#produce(T)} begin to work. + * set consumers to this Carrier. consumer begin to run when {@link DataCarrier#produce(T)} begin to work. * * @param consumerClass class of consumer * @param num number of consumer threads */ - public DataCarrier consume(Class> consumerClass, int num) { + public DataCarrier consume(Class> consumerClass, int num, long consumeCycle) { if (consumerPool != null) { consumerPool.close(); } - consumerPool = new ConsumerPool(this.channels, consumerClass, num); + consumerPool = new ConsumerPool(this.channels, consumerClass, num, consumeCycle); consumerPool.begin(); return this; } /** - * set consumers to this Carrier. - * consumer begin to run when {@link DataCarrier#produce(T)} begin to work. + * set consumers to this Carrier. consumer begin to run when {@link DataCarrier#produce(T)} begin to work with 20 + * millis consume cycle. + * + * @param consumerClass class of consumer + * @param num number of consumer threads + */ + public DataCarrier consume(Class> consumerClass, int num) { + return this.consume(consumerClass, num, 20); + } + + /** + * set consumers to this Carrier. consumer begin to run when {@link DataCarrier#produce(T)} begin to work. * * @param consumer single instance of consumer, all consumer threads will all use this instance. * @param num number of consumer threads * @return */ - public DataCarrier consume(IConsumer consumer, int num) { + public DataCarrier consume(IConsumer consumer, int num, long consumeCycle) { if (consumerPool != null) { consumerPool.close(); } - consumerPool = new ConsumerPool(this.channels, consumer, num); + consumerPool = new ConsumerPool(this.channels, consumer, num, consumeCycle); consumerPool.begin(); return this; } + /** + * set consumers to this Carrier. consumer begin to run when {@link DataCarrier#produce(T)} begin to work with 20 + * millis consume cycle. + * + * @param consumer single instance of consumer, all consumer threads will all use this instance. + * @param num number of consumer threads + * @return + */ + public DataCarrier consume(IConsumer consumer, int num) { + return this.consume(consumer, num, 20); + } + /** * shutdown all consumer threads, if consumer threads are running. Notice {@link BufferStrategy}: if {@link * BufferStrategy} == {@link BufferStrategy#BLOCKING}, shutdown consumers maybe cause blocking when producing. diff --git a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/buffer/Buffer.java b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/buffer/Buffer.java index 6ac79c47944bc5686cd2067fd16bf45e3a6cdb0f..4fbb47869388f544e0609b00cfaee754eb50d565 100644 --- a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/buffer/Buffer.java +++ b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/buffer/Buffer.java @@ -16,10 +16,11 @@ * */ - package org.apache.skywalking.apm.commons.datacarrier.buffer; import java.util.LinkedList; +import java.util.List; +import org.apache.skywalking.apm.commons.datacarrier.callback.QueueBlockingCallback; import org.apache.skywalking.apm.commons.datacarrier.common.AtomicRangeInteger; /** @@ -29,23 +30,36 @@ public class Buffer { private final Object[] buffer; private BufferStrategy strategy; private AtomicRangeInteger index; + private List> callbacks; Buffer(int bufferSize, BufferStrategy strategy) { buffer = new Object[bufferSize]; this.strategy = strategy; index = new AtomicRangeInteger(0, bufferSize); + callbacks = new LinkedList>(); } void setStrategy(BufferStrategy strategy) { this.strategy = strategy; } + void addCallback(QueueBlockingCallback callback) { + callbacks.add(callback); + } + boolean save(T data) { int i = index.getAndIncrement(); if (buffer[i] != null) { switch (strategy) { case BLOCKING: + boolean isFirstTimeBlocking = true; while (buffer[i] != null) { + if (isFirstTimeBlocking) { + isFirstTimeBlocking = false; + for (QueueBlockingCallback callback : callbacks) { + callback.notify(data); + } + } try { Thread.sleep(1L); } catch (InterruptedException e) { diff --git a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/buffer/Channels.java b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/buffer/Channels.java index bf4c03fd7dca202835b1601a06a8b183deff5881..4f7ee8754eef83de8cb7bee4534e4cba5d9cbf9d 100644 --- a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/buffer/Channels.java +++ b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/buffer/Channels.java @@ -16,17 +16,14 @@ * */ - package org.apache.skywalking.apm.commons.datacarrier.buffer; +import org.apache.skywalking.apm.commons.datacarrier.callback.QueueBlockingCallback; import org.apache.skywalking.apm.commons.datacarrier.partition.IDataPartitioner; /** - * Channels of Buffer - * It contais all buffer data which belongs to this channel. - * It supports several strategy when buffer is full. The Default is BLOCKING - *

- * Created by wusheng on 2016/10/25. + * Channels of Buffer It contais all buffer data which belongs to this channel. It supports several strategy when buffer + * is full. The Default is BLOCKING

Created by wusheng on 2016/10/25. */ public class Channels { private final Buffer[] bufferChannels; @@ -87,4 +84,10 @@ public class Channels { public Buffer getBuffer(int index) { return this.bufferChannels[index]; } + + public void addCallback(QueueBlockingCallback callback) { + for (Buffer channel : bufferChannels) { + channel.addCallback(callback); + } + } } diff --git a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/callback/QueueBlockingCallback.java b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/callback/QueueBlockingCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..c0a6c47c4284c74910e608b187129a507251aaab --- /dev/null +++ b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/callback/QueueBlockingCallback.java @@ -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. + * + */ + +package org.apache.skywalking.apm.commons.datacarrier.callback; + +/** + * Notify when the queue, which is in blocking strategy, has be blocked. + * + * @author wu-sheng + */ +public interface QueueBlockingCallback { + void notify(T message); +} diff --git a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerPool.java b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerPool.java index 6d127cca70d0e4c7c951376d0e5d7f241f96b883..814fdf8f8b6fd6ecd1931bf3eedda5d1a10d116b 100644 --- a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerPool.java +++ b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerPool.java @@ -16,7 +16,6 @@ * */ - package org.apache.skywalking.apm.commons.datacarrier.consumer; import java.util.ArrayList; @@ -25,9 +24,7 @@ import org.apache.skywalking.apm.commons.datacarrier.buffer.Buffer; import org.apache.skywalking.apm.commons.datacarrier.buffer.Channels; /** - * Pool of consumers - *

- * Created by wusheng on 2016/10/25. + * Pool of consumers

Created by wusheng on 2016/10/25. */ public class ConsumerPool { private boolean running; @@ -35,19 +32,19 @@ public class ConsumerPool { private Channels channels; private ReentrantLock lock; - public ConsumerPool(Channels channels, Class> consumerClass, int num) { + public ConsumerPool(Channels channels, Class> consumerClass, int num, long consumeCycle) { this(channels, num); for (int i = 0; i < num; i++) { - consumerThreads[i] = new ConsumerThread("DataCarrier.Consumser." + i + ".Thread", getNewConsumerInstance(consumerClass)); + consumerThreads[i] = new ConsumerThread("DataCarrier.Consumser." + i + ".Thread", getNewConsumerInstance(consumerClass), consumeCycle); consumerThreads[i].setDaemon(true); } } - public ConsumerPool(Channels channels, IConsumer prototype, int num) { + public ConsumerPool(Channels channels, IConsumer prototype, int num, long consumeCycle) { this(channels, num); prototype.init(); for (int i = 0; i < num; i++) { - consumerThreads[i] = new ConsumerThread("DataCarrier.Consumser." + i + ".Thread", prototype); + consumerThreads[i] = new ConsumerThread("DataCarrier.Consumser." + i + ".Thread", prototype, consumeCycle); consumerThreads[i].setDaemon(true); } diff --git a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerThread.java b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerThread.java index 891aac4656ecf7da297f85d7bdb8e9d1437c5254..1ba0223dbbfe294278bb8765934ea6ace5829318 100644 --- a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerThread.java +++ b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerThread.java @@ -30,12 +30,14 @@ public class ConsumerThread extends Thread { private volatile boolean running; private IConsumer consumer; private List dataSources; + private long consumeCycle; - ConsumerThread(String threadName, IConsumer consumer) { + ConsumerThread(String threadName, IConsumer consumer, long consumeCycle) { super(threadName); this.consumer = consumer; running = false; dataSources = new LinkedList(); + this.consumeCycle = consumeCycle; } /** @@ -67,7 +69,7 @@ public class ConsumerThread extends Thread { if (!hasData) { try { - Thread.sleep(20); + Thread.sleep(consumeCycle); } catch (InterruptedException e) { } } diff --git a/apm-commons/apm-datacarrier/src/test/java/org/apache/skywalking/apm/commons/datacarrier/DataCarrierTest.java b/apm-commons/apm-datacarrier/src/test/java/org/apache/skywalking/apm/commons/datacarrier/DataCarrierTest.java index ca7096c057d3487981d283f6a87607fec77fc922..85d767ed39dc75c11e496ca6907a2a6d81e2b4c3 100644 --- a/apm-commons/apm-datacarrier/src/test/java/org/apache/skywalking/apm/commons/datacarrier/DataCarrierTest.java +++ b/apm-commons/apm-datacarrier/src/test/java/org/apache/skywalking/apm/commons/datacarrier/DataCarrierTest.java @@ -128,7 +128,7 @@ public class DataCarrierTest { @Override public void run() { try { - Thread.sleep(2000); + Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/apm-commons/apm-datacarrier/src/test/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerPoolTest.java b/apm-commons/apm-datacarrier/src/test/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerPoolTest.java index 4daa51e4f792d0d73a3c58eeb6300e43a2635fda..18eab0eac30c53b0758bc925e68e3098077c07ac 100644 --- a/apm-commons/apm-datacarrier/src/test/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerPoolTest.java +++ b/apm-commons/apm-datacarrier/src/test/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumerPoolTest.java @@ -34,7 +34,7 @@ public class ConsumerPoolTest { @Test public void testBeginConsumerPool() throws IllegalAccessException { Channels channels = new Channels(2, 100, new SimpleRollingPartitioner(), BufferStrategy.BLOCKING); - ConsumerPool pool = new ConsumerPool(channels, new SampleConsumer(), 2); + ConsumerPool pool = new ConsumerPool(channels, new SampleConsumer(), 2, 20); pool.begin(); ConsumerThread[] threads = (ConsumerThread[])MemberModifier.field(ConsumerPool.class, "consumerThreads").get(pool); @@ -46,7 +46,7 @@ public class ConsumerPoolTest { @Test public void testCloseConsumerPool() throws InterruptedException, IllegalAccessException { Channels channels = new Channels(2, 100, new SimpleRollingPartitioner(), BufferStrategy.BLOCKING); - ConsumerPool pool = new ConsumerPool(channels, new SampleConsumer(), 2); + ConsumerPool pool = new ConsumerPool(channels, new SampleConsumer(), 2, 20); pool.begin(); Thread.sleep(5000); diff --git a/apm-network/pom.xml b/apm-protocol/apm-network/pom.xml similarity index 99% rename from apm-network/pom.xml rename to apm-protocol/apm-network/pom.xml index 7fbadf7bf3b4a6eb099ace2e01b6cd351c4c42d9..ceef97708906be7093e77835681932c06ddf6001 100644 --- a/apm-network/pom.xml +++ b/apm-protocol/apm-network/pom.xml @@ -21,7 +21,7 @@ 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"> - apm + apm-protocol org.apache.skywalking 5.0.0-alpha diff --git a/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/Component.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/Component.java similarity index 100% rename from apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/Component.java rename to apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/Component.java diff --git a/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java similarity index 100% rename from apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java rename to apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java diff --git a/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/OfficialComponent.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/OfficialComponent.java similarity index 100% rename from apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/OfficialComponent.java rename to apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/OfficialComponent.java diff --git a/apm-network/src/main/proto/ApplicationRegisterService.proto b/apm-protocol/apm-network/src/main/proto/ApplicationRegisterService.proto similarity index 86% rename from apm-network/src/main/proto/ApplicationRegisterService.proto rename to apm-protocol/apm-network/src/main/proto/ApplicationRegisterService.proto index 1852ee4edef3a6d0a05eff4a3af23faa8fcfc864..c612eb395d2e2681e3b32a0e9b4a61c9c2057b83 100644 --- a/apm-network/src/main/proto/ApplicationRegisterService.proto +++ b/apm-protocol/apm-network/src/main/proto/ApplicationRegisterService.proto @@ -7,6 +7,7 @@ import "KeyWithIntegerValue.proto"; //register service for ApplicationCode, this service is called when service starts. service ApplicationRegisterService { + //TODO: TODO: `batchRegister` should be replaces by applicationCodeRegister rpc batchRegister (Applications) returns (ApplicationMappings) { } } diff --git a/apm-network/src/main/proto/DiscoveryService.proto b/apm-protocol/apm-network/src/main/proto/DiscoveryService.proto similarity index 86% rename from apm-network/src/main/proto/DiscoveryService.proto rename to apm-protocol/apm-network/src/main/proto/DiscoveryService.proto index 5605c0d024e98a422d9bfca7f8b3569537f201f0..640b6d2d50a2bb2f94d5741963cc6ebf6b9ae2d5 100644 --- a/apm-network/src/main/proto/DiscoveryService.proto +++ b/apm-protocol/apm-network/src/main/proto/DiscoveryService.proto @@ -5,17 +5,14 @@ option java_package = "org.apache.skywalking.apm.network.proto"; import "Downstream.proto"; -//discovery service for application instance, this service is called when application starts -//or http client connection switch to another collector server instance service InstanceDiscoveryService { + //TODO: need rename, `register` is a key word. rpc register (ApplicationInstance) returns (ApplicationInstanceMapping) { } rpc heartbeat (ApplicationInstanceHeartbeat) returns (Downstream) { } - rpc registerRecover (ApplicationInstanceRecover) returns (Downstream) { - } } message ApplicationInstance { diff --git a/apm-network/src/main/proto/Downstream.proto b/apm-protocol/apm-network/src/main/proto/Downstream.proto similarity index 100% rename from apm-network/src/main/proto/Downstream.proto rename to apm-protocol/apm-network/src/main/proto/Downstream.proto diff --git a/apm-network/src/main/proto/JVMMetricsService.proto b/apm-protocol/apm-network/src/main/proto/JVMMetricsService.proto similarity index 100% rename from apm-network/src/main/proto/JVMMetricsService.proto rename to apm-protocol/apm-network/src/main/proto/JVMMetricsService.proto diff --git a/apm-network/src/main/proto/KeyWithIntegerValue.proto b/apm-protocol/apm-network/src/main/proto/KeyWithIntegerValue.proto similarity index 100% rename from apm-network/src/main/proto/KeyWithIntegerValue.proto rename to apm-protocol/apm-network/src/main/proto/KeyWithIntegerValue.proto diff --git a/apm-network/src/main/proto/KeyWithStringValue.proto b/apm-protocol/apm-network/src/main/proto/KeyWithStringValue.proto similarity index 100% rename from apm-network/src/main/proto/KeyWithStringValue.proto rename to apm-protocol/apm-network/src/main/proto/KeyWithStringValue.proto diff --git a/apm-protocol/apm-network/src/main/proto/NetworkAddressRegisterService.proto b/apm-protocol/apm-network/src/main/proto/NetworkAddressRegisterService.proto new file mode 100644 index 0000000000000000000000000000000000000000..15a6b31b02be87965ca175816cb25de2949a9886 --- /dev/null +++ b/apm-protocol/apm-network/src/main/proto/NetworkAddressRegisterService.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "org.apache.skywalking.apm.network.proto"; + +import "KeyWithIntegerValue.proto"; + +service NetworkAddressRegisterService { + rpc batchRegister (NetworkAddresses) returns (NetworkAddressMappings) { + } +} + +message NetworkAddresses { + repeated string addresses = 1; +} + +message NetworkAddressMappings { + repeated KeyWithIntegerValue addressIds = 1; +} diff --git a/apm-network/src/main/proto/TraceSegmentService.proto b/apm-protocol/apm-network/src/main/proto/TraceSegmentService.proto similarity index 100% rename from apm-network/src/main/proto/TraceSegmentService.proto rename to apm-protocol/apm-network/src/main/proto/TraceSegmentService.proto diff --git a/apm-network/src/test/java/org/apache/skywalking/apm/network/trace/proto/GRPCNoServerTest.java b/apm-protocol/apm-network/src/test/java/org/apache/skywalking/apm/network/trace/proto/GRPCNoServerTest.java similarity index 100% rename from apm-network/src/test/java/org/apache/skywalking/apm/network/trace/proto/GRPCNoServerTest.java rename to apm-protocol/apm-network/src/test/java/org/apache/skywalking/apm/network/trace/proto/GRPCNoServerTest.java diff --git a/apm-protocol/apm-ui-protocol/pom.xml b/apm-protocol/apm-ui-protocol/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e7e757843cbb301a678aa26ccac974c209b1d46 --- /dev/null +++ b/apm-protocol/apm-ui-protocol/pom.xml @@ -0,0 +1,39 @@ + + + + + + apm-protocol + org.apache.skywalking + 5.0.0-alpha + + 4.0.0 + + apm-ui-protocol + + + + com.graphql-java + graphql-java + 6.0 + + + diff --git a/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/README.md b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/README.md new file mode 100644 index 0000000000000000000000000000000000000000..60ddb04aa9615a31f852fda29c13b758557a8a76 --- /dev/null +++ b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/README.md @@ -0,0 +1,41 @@ +# Abstract +**apm-ui-protocol** declares all services, using GraphQL API style, which provide by Collector UI module. + +## Services +### [Common](common.graphqls) + +Include common objects, which used in global + +### [Overview Layer Service](overview-layer.graphqls) + +Query data without specific application, server or service. It includes info for overview the whole cluster. + +### [Application Layer Service](application-layer.graphqls) + +Query application related data with specific application code. + +### [Server Layer Service](server-layer.graphqls) + +Query server related data with specific server id. + +### [Service Layer Service](service-layer.graphqls) + +Query service related data with specific service id + +### [Trace Service](trace.graphqls) + +Query trace by some conditions. + +### [Alarm Service](alarm.graphqls) + +Query alarm info. + +## Version +v1alpha1 + +### Versioning +Use URI Versioning, to follow the most straightforward approach, +though it does violate the principle that a URI should refer to a unique resource. + +e.g. +http://collector.host/graphql/v1alpha1 diff --git a/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/alarm.graphqls b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/alarm.graphqls new file mode 100644 index 0000000000000000000000000000000000000000..b63946d8b2d67fcbcde133a942da7971145af90c --- /dev/null +++ b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/alarm.graphqls @@ -0,0 +1,15 @@ +type AlarmItem { + content: String! + startTime: String! + alertType: AlarmType! +} + +enum AlarmType { + APPLICATION, + SERVER, + SERVICE +} + +extend type Query { + loadAlertList(keyword: String, alertType: AlarmType, duration:Duration!):[AlarmItem] +} \ No newline at end of file diff --git a/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/application-layer.graphqls b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/application-layer.graphqls new file mode 100644 index 0000000000000000000000000000000000000000..ef9fc7007e775113baf1dd2fedb563620c60c32c --- /dev/null +++ b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/application-layer.graphqls @@ -0,0 +1,37 @@ +# ApplicationNode represents this node is under monitoring by agent. +type ApplicationNode implements Node { + id: ID! + name: String! + type: String + # Success rate of all incoming requests. + # Max value is 100. + # 2 Digits after floating point. + sla: Float! + # The number of incoming calls + calls: Long! + # ref: http://www.apdex.org/ + # Max value is 1 + # 2 Digits after floating point. + apdex: Float! + # The number of servers in the application code + numOfServer: Int! + # The number of servers alerting + numOfServerAlarm: Int! + # The number of services alerting + numOfServiceAlarm: Int! +} + +# The conjectural node generated by exit span +type ConjecturalNode implements Node { + id: ID! + name: String! + type: String +} + + +extend type Query { + getAllApplication(duration: Duration!): [ApplicationNode] + getApplicationTopology(applicationId: ID!, duration: Duration!): Topology + getSlowService(applicationId: ID!, duration: Duration!): [ServiceInfo!] + getServerThroughput(applicationId: ID!, duration: Duration!): [AppServerInfo!] +} diff --git a/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/common.graphqls b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/common.graphqls new file mode 100644 index 0000000000000000000000000000000000000000..853f362582a8b5bfb16a1b4576c970be805058e3 --- /dev/null +++ b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/common.graphqls @@ -0,0 +1,88 @@ +schema { + query: Query +} + +#Root node +type Query { + version: String +} + +# The Duration defines the start and end time for each query operation. +# Fields: `start` and `end` +# represents the time span. And each of them matches the step. +# ref https://www.ietf.org/rfc/rfc3339.txt +# The time formats are +# `SECOND` step: yyyy-MM-dd HHmmss +# `MINUTE` step: yyyy-MM-dd HHmm +# `HOUR` step: yyyy-MM-dd HH +# `DAY` step: yyyy-MM-dd +# `MONTH` step: yyyy-MM +# Field: `step` +# represents the accurate time point. +# e.g. +# if step==HOUR , start=2017-11-08 09, end=2017-11-08 19 +# then +# metrics from the following time points expected +# 2017-11-08 9:00 -> 2017-11-08 19:00 +# there are 11 time points (hours) in the time span. +input Duration { + start: String! + end: String! + step: Step! +} + +enum Step { + MONTH + DAY + HOUR + MINUTE + SECOND +} + +###################################### +# Common Metrics and Trends +###################################### +type ResponseTimeTrend { + trendList: [Int!] +} + +type ThroughputTrend { + trendList: [Int!] +} + +type SLATrend { + trendList: [Int!] +} + +# The overview topology of the whole application cluster or services, +type Topology { + nodes: [Node]! + calls: [Call] +} + +# The base Node of all node types in topology +interface Node { + # The global id of each node, + # 1. `Application ID` represents application under monitoring + # 2. `Peer ID` string represents the conjectural dependency. + id: ID! + # Application Code or literal Peer + name: String! + # The type name + # 1. The most important component in the application, from service provider perspective. + # 2. Conjectural dependent component, e.g. MySQL, Redis, Kafka + type: String +} + +# The Call represents a directed distributed call, +# from the `source` to the `target`. +type Call { + source: ID! + target: ID! + isAlert: Boolean + # The protocol and tech stack used in this distributed call + callType: String! + callsPerSec: Int! + # Unit: millisecond + responseTimePerSec: Int! +} diff --git a/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/overview-layer.graphqls b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/overview-layer.graphqls new file mode 100644 index 0000000000000000000000000000000000000000..e7b0bc2d65b1e3df0e162602169ca17642c013c1 --- /dev/null +++ b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/overview-layer.graphqls @@ -0,0 +1,37 @@ +# Query the cluster brief based on the given duration +type ClusterBrief { + numOfApplication: Int + numOfService: Int + numOfDatabase: Int + numOfCache: Int + numOfMQ: Int +} + +# Query the trend of alarm rate based on the given duration +type AlarmTrend { + numOfAlarmRate: [Int]! +} + +# Query all conjectural applications based on the given duration +# All applications here are not installed agent. +type ConjecturalAppBrief { + apps: [ConjecturalApp!] +} + +# The basic info of the conjectural application, +# includes the type and num of same type application +type ConjecturalApp { + # The display name of the application + # e.g. MySQL, RocketMQ, Kafka, Nginx + name: String! + num: Int! +} + +extend type Query { + getClusterTopology(duration: Duration!): Topology + getClusterBrief(duration: Duration!): ClusterBrief + getAlarmTrend(duration: Duration!): AlarmTrend + getConjecturalApps(duration: Duration!): ConjecturalAppBrief + getTopNSlowService(duration: Duration!, topN: Int!): [ServiceInfo!] + getTopNServerThroughput(duration: Duration!, topN: Int!): [AppServerInfo!] +} diff --git a/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/server-layer.graphqls b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/server-layer.graphqls new file mode 100644 index 0000000000000000000000000000000000000000..eac33a7dcf3f596b0702251db8cc8cfea8be0500 --- /dev/null +++ b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/server-layer.graphqls @@ -0,0 +1,42 @@ +# The server info. +# At here, `Server` represents a process in OS, +# e.g. +# 1. Spring boot application +# 2. A Tomcat server instance +type AppServerInfo { + id: ID! + name: String! + tps: Int! + os: String + host: String + pid: Int + IPv4: String + IPv6: String +} + +type CPUTrend { + cost: [Int!] +} + +# The gc trend represents the numbers of Garbage Collector execution +type GCTrend { + youngGC: [Int!] + oldGC: [Int!] +} + +# The memory used and max limit in heap and noheap space. +type MemoryTrend { + heap: [Int!] + maxHeap: [Int!] + noheap: [Int!] + maxNoheap: [Int!] +} + +extend type Query { + searchServer(keyword: String!, duration: Duration!): [AppServerInfo] + getServerResponseTimeTrend(serverId: ID!, duration: Duration!): ResponseTimeTrend + getServerTPSTrend(serverId: ID!, duration: Duration!): ThroughputTrend + getCPUTrend(serverId: ID!, duration: Duration!): CPUTrend + getGCTrend(serverId: ID!, duration: Duration!): GCTrend + getMemoryTrend(serverId: ID!, duration: Duration!): MemoryTrend +} \ No newline at end of file diff --git a/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/service-layer.graphqls b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/service-layer.graphqls new file mode 100644 index 0000000000000000000000000000000000000000..3e33c8f9e4f4f58f8dc39eb9a6a4b4a2c4a98d83 --- /dev/null +++ b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/service-layer.graphqls @@ -0,0 +1,35 @@ +type ServiceNode implements Node { + id: ID! + name: String! + type: String + # Success rate of all incoming requests. + # Max value is 100. + # 2 Digits after floating point. + sla: Float! + # The number of incoming calls + calls: Long! + # The number of services alerting + numOfServiceAlarm: Int! +} + +type ServiceInfo { + id: ID! + name: String + # The unit is millisecond. + avgResponseTime: Int! + tps: Int! +} + +type TraceItem { + time: String! + entry: String! + duration: Int! +} + +extend type Query { + searchService(keyword: String!, duration: Duration!): [ServiceNode] + getServiceResponseTimeTrend(serviceId: ID!, duration: Duration!): ResponseTimeTrend + getServiceTPSTrend(serviceId: ID!, duration: Duration!): ThroughputTrend + getServiceSLATrend(serviceId: ID!, duration: Duration!): SLATrend + getServiceTopology(serviceId: ID!, duration: Duration!): Topology +} diff --git a/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/trace.graphqls b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/trace.graphqls new file mode 100644 index 0000000000000000000000000000000000000000..4e2e1a0ec5ad9672080269faa0bb10ad43d1fe9a --- /dev/null +++ b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/trace.graphqls @@ -0,0 +1,89 @@ +# The list of traces +type TraceBrief { + traces: [BasicTrace!] +} + +# Trace basic info +type BasicTrace { + operationName: String! + duration: Int! + start: String! + isError: Boolean + traceId: String +} + +# Represent the conditions used for query TraceBrief +input TraceQueryCondition { + applicationCodes: [String!] + traceId: String + operationName: String + # The time range of traces started + queryDuration: Duration + # The mix time of trace + minTraceDuration: Int + # The max time of trace + maxTraceDuration: Int + topN: Boolean + needTotal: Int +} + +enum QueryOrder { + BY_START_TIME + BY_DURATION +} + +# The trace represents a distributed trace, includes all segments and spans. +type Trace { + traceId: ID! + segments: [Segment!] +} + +type Segment { + segmentId: ID! + appName: String! + isSizeLimited: Boolean! + spans: [Span!]! +} + +type Span { + refs: [Ref!] + spanId: Int! + parentSpanId: Int! + startTime: Long! + endTime: Long! + operationName: String + # There are three span types: Local, Entry and Exit + type: String! + # Peer network id, e.g. host+port, ip+port + peer: String + component: String + isError: Boolean + # There are 5 layers: Unknown, Database, RPCFramework, Http, MQ and Cache + layer: String + tags: [KeyValue!] + logs: [LogEntity!] +} + +# Ref represents the link between the segment and its parents. +type Ref { + parentSegmentId: ID! + parentSpanId: Int! + # Ref type represents why did the ref happen. + # Include: 1) CrossProcess 2) CrossThread + type: String! +} + +type KeyValue { + key: String! + value: String +} + +type LogEntity { + time: String + data: [KeyValue!] +} + +extend type Query { + queryBasicTraces(condition: TraceQueryCondition): TraceBrief + queryTrace(traceId: ID!): Trace +} \ No newline at end of file diff --git a/apm-protocol/apm-ui-protocol/src/test/java/org/apache/skywalking/apm/ui/protocol/GraphQLScriptTest.java b/apm-protocol/apm-ui-protocol/src/test/java/org/apache/skywalking/apm/ui/protocol/GraphQLScriptTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f017d6844147d105c1110eaf055b89edca2aff38 --- /dev/null +++ b/apm-protocol/apm-ui-protocol/src/test/java/org/apache/skywalking/apm/ui/protocol/GraphQLScriptTest.java @@ -0,0 +1,57 @@ +/* + * 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.apm.ui.protocol; + +import graphql.schema.idl.EchoingWiringFactory; +import graphql.schema.idl.RuntimeWiring; +import graphql.schema.idl.SchemaGenerator; +import graphql.schema.idl.SchemaParser; +import graphql.schema.idl.TypeDefinitionRegistry; +import java.io.File; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class GraphQLScriptTest { + + @Test + public void assertScriptFormat() { + SchemaParser schemaParser = new SchemaParser(); + SchemaGenerator schemaGenerator = new SchemaGenerator(); + + TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry(); + typeRegistry.merge(schemaParser.parse(loadSchema("common.graphqls"))); + typeRegistry.merge(schemaParser.parse(loadSchema("trace.graphqls"))); + typeRegistry.merge(schemaParser.parse(loadSchema("overview-layer.graphqls"))); + typeRegistry.merge(schemaParser.parse(loadSchema("application-layer.graphqls"))); + typeRegistry.merge(schemaParser.parse(loadSchema("server-layer.graphqls"))); + typeRegistry.merge(schemaParser.parse(loadSchema("service-layer.graphqls"))); + typeRegistry.merge(schemaParser.parse(loadSchema("alarm.graphqls"))); + RuntimeWiring wiring = buildRuntimeWiring(); + assertTrue(schemaGenerator.makeExecutableSchema(typeRegistry, wiring).getAllTypesAsList().size() > 0); + } + + private File loadSchema(final String s) { + return new File(GraphQLScriptTest.class.getClassLoader().getResource("ui-graphql/" + s).getFile()); + } + + private RuntimeWiring buildRuntimeWiring() { + return RuntimeWiring.newRuntimeWiring().wiringFactory(new EchoingWiringFactory()).build(); + } +} diff --git a/apm-protocol/pom.xml b/apm-protocol/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa5708532c69f0c8aaa312c7aa57ff0be77c4587 --- /dev/null +++ b/apm-protocol/pom.xml @@ -0,0 +1,37 @@ + + + + + + apm + org.apache.skywalking + 5.0.0-alpha + + 4.0.0 + + apm-protocol + pom + + + apm-network + apm-ui-protocol + + \ No newline at end of file diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index 6e398be8a3bd2e1d002b0374efb94b217b645769..9ea7e33d6686bc3c2be7da5cb54b68d50d3ce360 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -36,7 +36,7 @@ UTF-8 9.4.2.v20170220 1.8.0 - 1.7.6 + 1.7.9 org.apache.skywalking.apm.dependencies com.lmax.disruptor diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java index 5538a554c45aae46334e7cb37f88dd39fb57e2d0..2e674177f82b209a3e38acb0ced5c5ad54d44b0e 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java @@ -19,13 +19,6 @@ package org.apache.skywalking.apm.agent.core.conf; -import org.apache.skywalking.apm.agent.core.boot.AgentPackageNotFoundException; -import org.apache.skywalking.apm.agent.core.boot.AgentPackagePath; -import org.apache.skywalking.apm.agent.core.logging.api.ILog; -import org.apache.skywalking.apm.agent.core.logging.api.LogManager; -import org.apache.skywalking.apm.util.ConfigInitializer; -import org.apache.skywalking.apm.util.StringUtil; - import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -33,6 +26,12 @@ import java.io.InputStream; import java.util.Iterator; import java.util.Map; import java.util.Properties; +import org.apache.skywalking.apm.agent.core.boot.AgentPackageNotFoundException; +import org.apache.skywalking.apm.agent.core.boot.AgentPackagePath; +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.util.ConfigInitializer; +import org.apache.skywalking.apm.util.StringUtil; /** * The SnifferConfigInitializer initializes all configs in several way. @@ -44,6 +43,7 @@ public class SnifferConfigInitializer { private static final ILog logger = LogManager.getLogger(SnifferConfigInitializer.class); private static String CONFIG_FILE_NAME = "/config/agent.config"; private static String ENV_KEY_PREFIX = "skywalking."; + private static boolean IS_INIT_COMPLETED = false; /** * Try to locate `agent.config`, which should be in the /config dictionary of agent package. @@ -78,6 +78,12 @@ public class SnifferConfigInitializer { if (StringUtil.isEmpty(Config.Collector.SERVERS)) { throw new ExceptionInInitializerError("`collector.servers` is missing."); } + + IS_INIT_COMPLETED = true; + } + + public static boolean isInitCompleted() { + return IS_INIT_COMPLETED; } /** diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java index 63e257f42ae715432ed221cc1abaeaabcb4ac8e4..cbbad7f67a21fec8cab498fdd1d9abb441a3d3b3 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java @@ -323,7 +323,7 @@ public class TracingContext implements AbstractTracerContext { exitSpan = parentSpan; } else { final int parentSpanId = parentSpan == null ? -1 : parentSpan.getSpanId(); - exitSpan = (AbstractSpan)DictionaryManager.findApplicationCodeSection() + exitSpan = (AbstractSpan)DictionaryManager.findNetworkAddressSection() .find(remotePeer).doInCondition( new PossibleFound.FoundAndObtain() { @Override diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/dictionary/DictionaryManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/dictionary/DictionaryManager.java index 3ce08c644555a9b1d12cf1c1d26fbafec39b2ac4..7d354320837078e316ce45c5e7405c9212b621e1 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/dictionary/DictionaryManager.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/dictionary/DictionaryManager.java @@ -24,10 +24,10 @@ package org.apache.skywalking.apm.agent.core.dictionary; */ public class DictionaryManager { /** - * @return {@link ApplicationDictionary} to find application id for application code and network address. + * @return {@link NetworkAddressDictionary} to find application id for application code and network address. */ - public static ApplicationDictionary findApplicationCodeSection() { - return ApplicationDictionary.INSTANCE; + public static NetworkAddressDictionary findNetworkAddressSection() { + return NetworkAddressDictionary.INSTANCE; } /** diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/dictionary/ApplicationDictionary.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/dictionary/NetworkAddressDictionary.java similarity index 65% rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/dictionary/ApplicationDictionary.java rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/dictionary/NetworkAddressDictionary.java index 28d934b0b64ef59fc3ef647fd9a2c69d316e4088..b48b02446363013d6ed02cf1b22deaae372d85eb 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/dictionary/ApplicationDictionary.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/dictionary/NetworkAddressDictionary.java @@ -23,42 +23,42 @@ import io.netty.util.internal.ConcurrentSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import org.apache.skywalking.apm.network.proto.ApplicationMappings; -import org.apache.skywalking.apm.network.proto.ApplicationRegisterServiceGrpc; -import org.apache.skywalking.apm.network.proto.Applications; import org.apache.skywalking.apm.network.proto.KeyWithIntegerValue; +import org.apache.skywalking.apm.network.proto.NetworkAddressMappings; +import org.apache.skywalking.apm.network.proto.NetworkAddressRegisterServiceGrpc; +import org.apache.skywalking.apm.network.proto.NetworkAddresses; import static org.apache.skywalking.apm.agent.core.conf.Config.Dictionary.APPLICATION_CODE_BUFFER_SIZE; /** - * Map of application id to application code, which is from the collector side. + * Map of network address id to network literal address, which is from the collector side. * * @author wusheng */ -public enum ApplicationDictionary { +public enum NetworkAddressDictionary { INSTANCE; private Map applicationDictionary = new ConcurrentHashMap(); private Set unRegisterApplications = new ConcurrentSet(); - public PossibleFound find(String applicationCode) { - Integer applicationId = applicationDictionary.get(applicationCode); + public PossibleFound find(String networkAddress) { + Integer applicationId = applicationDictionary.get(networkAddress); if (applicationId != null) { return new Found(applicationId); } else { if (applicationDictionary.size() + unRegisterApplications.size() < APPLICATION_CODE_BUFFER_SIZE) { - unRegisterApplications.add(applicationCode); + unRegisterApplications.add(networkAddress); } return new NotFound(); } } public void syncRemoteDictionary( - ApplicationRegisterServiceGrpc.ApplicationRegisterServiceBlockingStub applicationRegisterServiceBlockingStub) { + NetworkAddressRegisterServiceGrpc.NetworkAddressRegisterServiceBlockingStub networkAddressRegisterServiceBlockingStub) { if (unRegisterApplications.size() > 0) { - ApplicationMappings applicationMapping = applicationRegisterServiceBlockingStub.batchRegister( - Applications.newBuilder().addAllApplicationCodes(unRegisterApplications).build()); - if (applicationMapping.getApplicationsCount() > 0) { - for (KeyWithIntegerValue keyWithIntegerValue : applicationMapping.getApplicationsList()) { + NetworkAddressMappings networkAddressMappings = networkAddressRegisterServiceBlockingStub.batchRegister( + NetworkAddresses.newBuilder().addAllAddresses(unRegisterApplications).build()); + if (networkAddressMappings.getAddressIdsCount() > 0) { + for (KeyWithIntegerValue keyWithIntegerValue : networkAddressMappings.getAddressIdsList()) { unRegisterApplications.remove(keyWithIntegerValue.getKey()); applicationDictionary.put(keyWithIntegerValue.getKey(), keyWithIntegerValue.getValue()); } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/ILog.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/ILog.java index 0589c2659c55279a33ed367e5ffdbbe68aefd5f9..5c4d4960851d2e0aa3bd56a3ebd607aff2c8deb2 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/ILog.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/ILog.java @@ -33,6 +33,8 @@ public interface ILog { void warn(String format, Object... arguments); + void warn(Throwable e, String format, Object... arguments); + void error(String format, Throwable e); void error(Throwable e, String format, Object... arguments); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/NoopLogger.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/NoopLogger.java index 6aa243c7b068a224784f1cd52cc9924652f6ae09..2ad720692b3e9da1bd24d3153aaecf4dfd575901 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/NoopLogger.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/NoopLogger.java @@ -26,9 +26,7 @@ package org.apache.skywalking.apm.agent.core.logging.api; * Created by xin on 2016/11/10. */ public enum NoopLogger implements ILog { - INSTANCE { - - }; + INSTANCE; @Override public void info(String message) { @@ -89,4 +87,10 @@ public enum NoopLogger implements ILog { public void error(Throwable e, String format, Object... arguments) { } + + + @Override + public void warn(Throwable e, String format, Object... arguments) { + + } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogger.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogger.java index d7c423616235e2e1cada6b31697b78a2e6f6773f..c8e5845adb53eeab684207e17e3c26a383ebf44b 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogger.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogger.java @@ -105,6 +105,12 @@ public class EasyLogger implements ILog { logger(LogLevel.WARN, replaceParam(format, arguments), null); } + @Override + public void warn(Throwable e, String format, Object... arguments) { + if (isWarnEnable()) + logger(LogLevel.WARN, replaceParam(format, arguments), e); + } + @Override public void error(String format, Throwable e) { if (isErrorEnable()) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java index 9ee6ebf52594d2463d1ef694f6104a1c440662dd..4bc357d2dfb0d0027a573c216fabe030cfada659 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java @@ -22,11 +22,12 @@ package org.apache.skywalking.apm.agent.core.logging.core; import org.apache.skywalking.apm.agent.core.boot.AgentPackageNotFoundException; import org.apache.skywalking.apm.agent.core.boot.AgentPackagePath; import org.apache.skywalking.apm.agent.core.conf.Config; +import org.apache.skywalking.apm.agent.core.conf.SnifferConfigInitializer; import org.apache.skywalking.apm.util.StringUtil; public class WriterFactory { public static IWriter getLogWriter() { - if (AgentPackagePath.isPathFound()) { + if (SnifferConfigInitializer.isInitCompleted() && AgentPackagePath.isPathFound()) { if (StringUtil.isEmpty(Config.Logging.DIR)) { try { Config.Logging.DIR = AgentPackagePath.getPath() + "/logs"; diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginFinder.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginFinder.java index 09606c05e952f896e67aa2efa02e1e86f80c4976..99e49a50ce238f88ea1c2a70ff4fb3fdd968eb81 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginFinder.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginFinder.java @@ -30,6 +30,7 @@ import org.apache.skywalking.apm.agent.core.plugin.bytebuddy.AbstractJunction; import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import org.apache.skywalking.apm.agent.core.plugin.match.IndirectMatch; import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.ProtectiveShieldMatcher; import static net.bytebuddy.matcher.ElementMatchers.isInterface; import static net.bytebuddy.matcher.ElementMatchers.not; @@ -98,6 +99,6 @@ public class PluginFinder { judge = judge.or(((IndirectMatch)match).buildJunction()); } } - return judge; + return new ProtectiveShieldMatcher(judge); } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/match/ProtectiveShieldMatcher.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/match/ProtectiveShieldMatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..a4c70276529ea23f0a5cddc44b0baeeb6da09d8a --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/match/ProtectiveShieldMatcher.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.skywalking.apm.agent.core.plugin.match; + +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; + +/** + * In some cases, some frameworks and libraries use some binary codes tech too. From the community feedback, some of + * them have compatible issues with byte-buddy core, which trigger "Can't resolve type description" exception. + * + * So I build this protective shield by a nested matcher. When the origin matcher(s) can't resolve the type, the + * SkyWalking agent ignores this types. + * + * Notice: this ignore mechanism may miss some instrumentations, but at most cases, it's same. If missing happens, + * please pay attention to the WARNING logs. + * + * @author wu-sheng + */ +public class ProtectiveShieldMatcher extends ElementMatcher.Junction.AbstractBase { + private static final ILog logger = LogManager.getLogger(ProtectiveShieldMatcher.class); + + private final ElementMatcher matcher; + + public ProtectiveShieldMatcher(ElementMatcher matcher) { + this.matcher = matcher; + } + + public boolean matches(T target) { + try { + return this.matcher.matches(target); + } catch (Throwable t) { + logger.warn(t, "Byte-buddy occurs exception when match type."); + return false; + } + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/AppAndServiceRegisterClient.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/AppAndServiceRegisterClient.java index 61cbd51722dcc250d86ef7f22bdc7354b2826b63..3ebe836ac7822a7fa660a0bae4b88912331aac2c 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/AppAndServiceRegisterClient.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/AppAndServiceRegisterClient.java @@ -16,7 +16,6 @@ * */ - package org.apache.skywalking.apm.agent.core.remote; import io.grpc.ManagedChannel; @@ -24,28 +23,28 @@ import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.apache.skywalking.apm.agent.core.conf.RemoteDownstreamConfig; -import org.apache.skywalking.apm.agent.core.context.TracingContext; -import org.apache.skywalking.apm.agent.core.dictionary.ApplicationDictionary; -import org.apache.skywalking.apm.agent.core.os.OSUtil; import org.apache.skywalking.apm.agent.core.boot.BootService; import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory; import org.apache.skywalking.apm.agent.core.boot.ServiceManager; import org.apache.skywalking.apm.agent.core.conf.Config; +import org.apache.skywalking.apm.agent.core.conf.RemoteDownstreamConfig; +import org.apache.skywalking.apm.agent.core.context.TracingContext; import org.apache.skywalking.apm.agent.core.context.TracingContextListener; import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; import org.apache.skywalking.apm.agent.core.dictionary.DictionaryUtil; +import org.apache.skywalking.apm.agent.core.dictionary.NetworkAddressDictionary; import org.apache.skywalking.apm.agent.core.dictionary.OperationNameDictionary; import org.apache.skywalking.apm.agent.core.logging.api.ILog; import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.agent.core.os.OSUtil; import org.apache.skywalking.apm.network.proto.ApplicationInstance; import org.apache.skywalking.apm.network.proto.ApplicationInstanceHeartbeat; import org.apache.skywalking.apm.network.proto.ApplicationInstanceMapping; -import org.apache.skywalking.apm.network.proto.ApplicationInstanceRecover; import org.apache.skywalking.apm.network.proto.ApplicationMappings; import org.apache.skywalking.apm.network.proto.ApplicationRegisterServiceGrpc; import org.apache.skywalking.apm.network.proto.Applications; import org.apache.skywalking.apm.network.proto.InstanceDiscoveryServiceGrpc; +import org.apache.skywalking.apm.network.proto.NetworkAddressRegisterServiceGrpc; import org.apache.skywalking.apm.network.proto.ServiceNameDiscoveryServiceGrpc; /** @@ -59,8 +58,8 @@ public class AppAndServiceRegisterClient implements BootService, GRPCChannelList private volatile ApplicationRegisterServiceGrpc.ApplicationRegisterServiceBlockingStub applicationRegisterServiceBlockingStub; private volatile InstanceDiscoveryServiceGrpc.InstanceDiscoveryServiceBlockingStub instanceDiscoveryServiceBlockingStub; private volatile ServiceNameDiscoveryServiceGrpc.ServiceNameDiscoveryServiceBlockingStub serviceNameDiscoveryServiceBlockingStub; + private volatile NetworkAddressRegisterServiceGrpc.NetworkAddressRegisterServiceBlockingStub networkAddressRegisterServiceBlockingStub; private volatile ScheduledFuture applicationRegisterFuture; - private volatile boolean needRegisterRecover = false; private volatile long lastSegmentTime = -1; @Override @@ -69,10 +68,8 @@ public class AppAndServiceRegisterClient implements BootService, GRPCChannelList ManagedChannel channel = ServiceManager.INSTANCE.findService(GRPCChannelManager.class).getManagedChannel(); applicationRegisterServiceBlockingStub = ApplicationRegisterServiceGrpc.newBlockingStub(channel); instanceDiscoveryServiceBlockingStub = InstanceDiscoveryServiceGrpc.newBlockingStub(channel); - if (RemoteDownstreamConfig.Agent.APPLICATION_INSTANCE_ID != DictionaryUtil.nullValue()) { - needRegisterRecover = true; - } serviceNameDiscoveryServiceBlockingStub = ServiceNameDiscoveryServiceGrpc.newBlockingStub(channel); + networkAddressRegisterServiceBlockingStub = NetworkAddressRegisterServiceGrpc.newBlockingStub(channel); } else { applicationRegisterServiceBlockingStub = null; instanceDiscoveryServiceBlockingStub = null; @@ -105,13 +102,14 @@ public class AppAndServiceRegisterClient implements BootService, GRPCChannelList @Override public void run() { - logger.debug("AppAndServiceRegisterClient running, status:{}.",status); + logger.debug("AppAndServiceRegisterClient running, status:{}.", status); boolean shouldTry = true; while (GRPCChannelStatus.CONNECTED.equals(status) && shouldTry) { shouldTry = false; try { if (RemoteDownstreamConfig.Agent.APPLICATION_ID == DictionaryUtil.nullValue()) { if (applicationRegisterServiceBlockingStub != null) { + //TODO: `batchRegister` should be replaces by applicationCodeRegister ApplicationMappings applicationMapping = applicationRegisterServiceBlockingStub.batchRegister( Applications.newBuilder().addApplicationCodes(Config.Agent.APPLICATION_CODE).build()); if (applicationMapping.getApplicationsCount() > 0) { @@ -134,24 +132,14 @@ public class AppAndServiceRegisterClient implements BootService, GRPCChannelList = instanceMapping.getApplicationInstanceId(); } } else { - if (needRegisterRecover) { - instanceDiscoveryServiceBlockingStub.registerRecover(ApplicationInstanceRecover.newBuilder() - .setApplicationId(RemoteDownstreamConfig.Agent.APPLICATION_ID) + if (lastSegmentTime - System.currentTimeMillis() > 60 * 1000) { + instanceDiscoveryServiceBlockingStub.heartbeat(ApplicationInstanceHeartbeat.newBuilder() .setApplicationInstanceId(RemoteDownstreamConfig.Agent.APPLICATION_INSTANCE_ID) - .setRegisterTime(System.currentTimeMillis()) - .setOsinfo(OSUtil.buildOSInfo()) + .setHeartbeatTime(System.currentTimeMillis()) .build()); - needRegisterRecover = false; - } else { - if (lastSegmentTime - System.currentTimeMillis() > 60 * 1000) { - instanceDiscoveryServiceBlockingStub.heartbeat(ApplicationInstanceHeartbeat.newBuilder() - .setApplicationInstanceId(RemoteDownstreamConfig.Agent.APPLICATION_INSTANCE_ID) - .setHeartbeatTime(System.currentTimeMillis()) - .build()); - } } - ApplicationDictionary.INSTANCE.syncRemoteDictionary(applicationRegisterServiceBlockingStub); + NetworkAddressDictionary.INSTANCE.syncRemoteDictionary(networkAddressRegisterServiceBlockingStub); OperationNameDictionary.INSTANCE.syncRemoteDictionary(serviceNameDiscoveryServiceBlockingStub); } } diff --git a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/feign/http/v9/DefaultHttpClientInterceptor.java b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/feign/http/v9/DefaultHttpClientInterceptor.java index b49b1fd2c9e3f4d2f970a9a6f1e3bb6d4ae8c380..eef05b7efa6b2c55d441a3d5793d6fd143412746 100644 --- a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/feign/http/v9/DefaultHttpClientInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/feign/http/v9/DefaultHttpClientInterceptor.java @@ -16,7 +16,6 @@ * */ - package org.apache.skywalking.apm.plugin.feign.http.v9; import feign.Request; @@ -52,9 +51,9 @@ public class DefaultHttpClientInterceptor implements InstanceMethodsAroundInterc private static final String COMPONENT_NAME = "FeignDefaultHttp"; /** - * Get the {@link feign.Request} from {@link EnhancedInstance}, then create {@link AbstractSpan} and set host, - * port, kind, component, url from {@link feign.Request}. - * Through the reflection of the way, set the http header of context data into {@link feign.Request#headers}. + * Get the {@link feign.Request} from {@link EnhancedInstance}, then create {@link AbstractSpan} and set host, port, + * kind, component, url from {@link feign.Request}. Through the reflection of the way, set the http header of + * context data into {@link feign.Request#headers}. * * @param method * @param result change this result, if you want to truncate the method. @@ -66,11 +65,16 @@ public class DefaultHttpClientInterceptor implements InstanceMethodsAroundInterc URL url = new URL(request.url()); ContextCarrier contextCarrier = new ContextCarrier(); - String remotePeer = url.getHost() + ":" + url.getPort(); - AbstractSpan span = ContextManager.createExitSpan(request.url(), contextCarrier, remotePeer); + int port = url.getPort() == -1 ? 80 : url.getPort(); + String remotePeer = url.getHost() + ":" + port; + String operationName = url.getPath(); + if (operationName == null || operationName.length() == 0) { + operationName = "/"; + } + AbstractSpan span = ContextManager.createExitSpan(operationName, contextCarrier, remotePeer); span.setComponent(ComponentsDefine.FEIGN); Tags.HTTP.METHOD.set(span, request.method()); - Tags.URL.set(span, url.getPath()); + Tags.URL.set(span, request.url()); SpanLayer.asHttp(span); Field headersField = Request.class.getDeclaredField("headers"); @@ -94,8 +98,7 @@ public class DefaultHttpClientInterceptor implements InstanceMethodsAroundInterc /** * Get the status code from {@link Response}, when status code greater than 400, it means there was some errors in - * the server. - * Finish the {@link AbstractSpan}. + * the server. Finish the {@link AbstractSpan}. * * @param method * @param ret the method's original return value. diff --git a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/feign/http/v9/DefaultHttpClientInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/feign/http/v9/DefaultHttpClientInterceptorTest.java index 1c5d30a1a211247100a9ee95d27452a7d26d6931..20f2ccfe92c5bdc6fc728e6e5ed1b8be8ee7f191 100644 --- a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/feign/http/v9/DefaultHttpClientInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/feign/http/v9/DefaultHttpClientInterceptorTest.java @@ -87,7 +87,7 @@ public class DefaultHttpClientInterceptorTest { public void setUp() throws Exception { Map> headers = new LinkedHashMap>(); - request = Request.create("GET", "http://skywalking.org", headers, "Test".getBytes(), Charset.forName("UTF-8")); + request = Request.create("GET", "http://skywalking.org/", headers, "Test".getBytes(), Charset.forName("UTF-8")); Request.Options options = new Request.Options(); allArguments = new Object[] {request, options}; argumentTypes = new Class[] {request.getClass(), options.getClass()}; @@ -112,7 +112,7 @@ public class DefaultHttpClientInterceptorTest { List tags = SpanHelper.getTags(finishedSpan); assertThat(tags.size(), is(2)); assertThat(tags.get(0).getValue(), is("GET")); - assertThat(tags.get(1).getValue(), is("")); + assertThat(tags.get(1).getValue(), is("http://skywalking.org/")); Assert.assertEquals(false, SpanHelper.getErrorOccurred(finishedSpan)); } @@ -135,7 +135,7 @@ public class DefaultHttpClientInterceptorTest { List tags = SpanHelper.getTags(finishedSpan); assertThat(tags.size(), is(3)); assertThat(tags.get(0).getValue(), is("GET")); - assertThat(tags.get(1).getValue(), is("")); + assertThat(tags.get(1).getValue(), is("http://skywalking.org/")); assertThat(tags.get(2).getValue(), is("404")); Assert.assertEquals(true, SpanHelper.getErrorOccurred(finishedSpan)); @@ -166,7 +166,7 @@ public class DefaultHttpClientInterceptorTest { List tags = SpanHelper.getTags(finishedSpan); assertThat(tags.size(), is(2)); assertThat(tags.get(0).getValue(), is("GET")); - assertThat(tags.get(1).getValue(), is("")); + assertThat(tags.get(1).getValue(), is("http://skywalking.org/")); Assert.assertEquals(true, SpanHelper.getErrorOccurred(finishedSpan)); diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java index 024218c8fafdbc560fbcf034f80e4e4c1d10e663..bc62c5532b434e4abfe80136d2acbe740f690b5b 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java @@ -16,22 +16,22 @@ * */ - package org.apache.skywalking.apm.plugin.httpClient.v4; +import io.netty.handler.codec.http.HttpScheme; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; -import org.apache.skywalking.apm.agent.core.context.CarrierItem; -import org.apache.skywalking.apm.agent.core.context.ContextManager; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; @@ -48,7 +48,10 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterc HttpRequest httpRequest = (HttpRequest)allArguments[1]; final ContextCarrier contextCarrier = new ContextCarrier(); AbstractSpan span = null; - String remotePeer = httpHost.getHostName() + ":" + httpHost.getPort(); + + String remotePeer = httpHost.getHostName() + ":" + (httpHost.getPort() > 0 ? httpHost.getPort() : + HttpScheme.HTTPS.name().equals(httpHost.getSchemeName().toLowerCase()) ? 443 : 80); + try { URL url = new URL(httpRequest.getRequestLine().getUri()); span = ContextManager.createExitSpan(url.getPath(), contextCarrier, remotePeer); diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptor.java index d595ae8d1e4124b494230ceda02038a3b1605990..63fc9c58ed2f8077d59db98f295274a759438ea8 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptor.java @@ -16,22 +16,22 @@ * */ - package org.apache.skywalking.apm.plugin.jetty.v9.client; import java.lang.reflect.Method; import org.apache.skywalking.apm.agent.core.context.CarrierItem; import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.http.HttpFields; -import org.apache.skywalking.apm.agent.core.context.ContextManager; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.eclipse.jetty.http.HttpMethod; public class SyncHttpRequestSendInterceptor implements InstanceMethodsAroundInterceptor { @@ -42,7 +42,19 @@ public class SyncHttpRequestSendInterceptor implements InstanceMethodsAroundInte ContextCarrier contextCarrier = new ContextCarrier(); AbstractSpan span = ContextManager.createExitSpan(request.getURI().getPath(), contextCarrier, request.getHost() + ":" + request.getPort()); span.setComponent(ComponentsDefine.JETTY_CLIENT); - Tags.HTTP.METHOD.set(span, "GET"); + HttpMethod httpMethod = HttpMethod.GET; + + /** + * The method is null if the client using GET method. + * + * @see org.eclipse.jetty.client.HttpRequest#GET(String uri) + * @see org.eclipse.jetty.client.HttpRequest( org.eclipse.jetty.client.HttpClient client, long conversation, java.net.URI uri) + */ + if (request.getMethod() != null) { + httpMethod = request.getMethod(); + } + + Tags.HTTP.METHOD.set(span, httpMethod.asString()); Tags.URL.set(span, request.getURI().toString()); SpanLayer.asHttp(span); diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/define/HttpRequestInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/define/HttpRequestInstrumentation.java index 2946eac1f73669850bfc4ad759832ce898371d52..147006dee66fbac2b770d9ad458a0653d0eae5e0 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/define/HttpRequestInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/define/HttpRequestInstrumentation.java @@ -21,15 +21,14 @@ package org.apache.skywalking.apm.plugin.jetty.v9.client.define; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; /** * {@link HttpRequestInstrumentation} enhance the send method without argument in @@ -43,8 +42,7 @@ public class HttpRequestInstrumentation extends ClassInstanceMethodsEnhancePlugi private static final String ENHANCE_CLASS = "org.eclipse.jetty.client.HttpRequest"; private static final String ENHANCE_CLASS_NAME = "send"; - public static final String ASYNC_SEND_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jetty.client.AsyncHttpRequestSendInterceptor"; - public static final String SYNC_SEND_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jetty.client.SyncHttpRequestSendInterceptor"; + public static final String SYNC_SEND_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jetty.v9.client.SyncHttpRequestSendInterceptor"; @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { return new ConstructorInterceptPoint[0]; @@ -62,20 +60,6 @@ public class HttpRequestInstrumentation extends ClassInstanceMethodsEnhancePlugi return SYNC_SEND_INTERCEPTOR; } - @Override public boolean isOverrideArgs() { - return false; - } - }, - new InstanceMethodsInterceptPoint() { - //async call interceptor point - @Override public ElementMatcher getMethodsMatcher() { - return named(ENHANCE_CLASS_NAME).and(takesArgumentWithType(0, "org.eclipse.jetty.client.api.Response$CompleteListener")); - } - - @Override public String getMethodsInterceptor() { - return ASYNC_SEND_INTERCEPTOR; - } - @Override public boolean isOverrideArgs() { return false; } diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/resources/skywalking-plugin.def index 2a8febe61d410ca18332887051bb8684b6e0eae3..32e602e048241a2f0ff2ca9f3bb49c50e4b4fb35 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/resources/skywalking-plugin.def @@ -1,2 +1 @@ -jetty-client-9.x=org.apache.skywalking.apm.plugin.jetty.v9.client.define.CompleteListenerInstrumentation jetty-client-9.x=org.apache.skywalking.apm.plugin.jetty.v9.client.define.HttpRequestInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java deleted file mode 100644 index ca8f7f3efc161d4c0b8378cd207f747c3610c652..0000000000000000000000000000000000000000 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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.apm.plugin.jetty.v9.client; - -import java.net.URI; -import java.util.List; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; -import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; -import org.apache.skywalking.apm.agent.core.context.util.KeyValuePair; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; -import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; -import org.apache.skywalking.apm.agent.test.helper.SpanHelper; -import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; -import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; -import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; -import org.apache.skywalking.apm.agent.test.tools.SpanAssert; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpRequest; -import org.eclipse.jetty.http.HttpMethod; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.modules.junit4.PowerMockRunnerDelegate; -import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; - -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - -@RunWith(PowerMockRunner.class) -@PowerMockRunnerDelegate(TracingSegmentRunner.class) -public class AsyncHttpRequestSendInterceptorTest { - - @SegmentStoragePoint - private SegmentStorage segmentStorage; - @Rule - public AgentServiceRule serviceRule = new AgentServiceRule(); - @Mock - private HttpClient httpClient; - @Mock - private EnhancedInstance callBackEnhanceInstance; - - private Object[] allArguments; - private Class[] argumentTypes; - private MockHttpRequest enhancedInstance; - private AsyncHttpRequestSendInterceptor interceptor; - private URI uri = URI.create("http://localhost:8080/test"); - - @Before - public void setUp() throws Exception { - enhancedInstance = new MockHttpRequest(httpClient, uri); - allArguments = new Object[] {"OperationKey", "OperationValue"}; - argumentTypes = new Class[] {String.class, String.class}; - - interceptor = new AsyncHttpRequestSendInterceptor(); - allArguments = new Object[] {callBackEnhanceInstance}; - } - - @Test - public void testMethodsAround() throws Throwable { - interceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, null); - interceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, null); - - assertThat(segmentStorage.getTraceSegments().size(), is(1)); - TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); - - Assert.assertEquals(1, SegmentHelper.getSpans(traceSegment).size()); - AbstractTracingSpan finishedSpan = SegmentHelper.getSpans(traceSegment).get(0); - - List tags = SpanHelper.getTags(finishedSpan); - assertThat(tags.size(), is(2)); - assertThat(tags.get(0).getValue(), is("POST")); - assertThat(tags.get(1).getValue(), is(uri.toString())); - - Assert.assertEquals(false, SpanHelper.getErrorOccurred(finishedSpan)); - } - - @Test - public void testMethodsAroundError() throws Throwable { - interceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, null); - interceptor.handleMethodException(enhancedInstance, null, allArguments, argumentTypes, new RuntimeException()); - interceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, null); - - assertThat(segmentStorage.getTraceSegments().size(), is(1)); - TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); - - Assert.assertEquals(1, SegmentHelper.getSpans(traceSegment).size()); - AbstractTracingSpan finishedSpan = SegmentHelper.getSpans(traceSegment).get(0); - - List tags = SpanHelper.getTags(finishedSpan); - assertThat(tags.size(), is(2)); - assertThat(tags.get(0).getValue(), is("POST")); - assertThat(tags.get(1).getValue(), is(uri.toString())); - - Assert.assertEquals(true, SpanHelper.getErrorOccurred(finishedSpan)); - SpanAssert.assertException(SpanHelper.getLogs(finishedSpan).get(0), RuntimeException.class); - - } - - private class MockHttpRequest extends HttpRequest implements EnhancedInstance { - public MockHttpRequest(HttpClient httpClient, URI uri) { - super(httpClient, uri); - } - - @Override public Object getSkyWalkingDynamicField() { - return null; - } - - @Override public void setSkyWalkingDynamicField(Object value) { - - } - - @Override public HttpMethod getMethod() { - return HttpMethod.POST; - } - - @Override public URI getURI() { - return uri; - } - } -} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptorTest.java deleted file mode 100644 index bcea6c1538bc0ef1be49b0d5209203b1a422d673..0000000000000000000000000000000000000000 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptorTest.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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.apm.plugin.jetty.v9.client; - -import java.net.URI; -import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; -import org.apache.skywalking.apm.agent.core.context.ids.DistributedTraceId; -import org.apache.skywalking.apm.agent.core.context.ids.ID; -import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; -import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; -import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; -import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; -import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; -import org.eclipse.jetty.client.HttpRequest; -import org.eclipse.jetty.client.HttpResponse; -import org.eclipse.jetty.client.api.Result; -import org.eclipse.jetty.http.HttpFields; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.modules.junit4.PowerMockRunnerDelegate; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.powermock.api.mockito.PowerMockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; - -@RunWith(PowerMockRunner.class) -@PowerMockRunnerDelegate(TracingSegmentRunner.class) -public class CompleteListenerInterceptorTest { - - @SegmentStoragePoint - private SegmentStorage segmentStorage; - @Rule - public AgentServiceRule serviceRule = new AgentServiceRule(); - @Mock - private Result result; - @Mock - private HttpRequest httpRequest; - @Mock - private HttpResponse httpResponse; - private Object[] allArguments; - private Class[] argumentTypes; - private CompleteListenerInterceptor interceptor; - - @Mock - private ContextSnapshot contextSnapshot; - - private EnhancedInstance objectInstanceWithoutSnapshot = new EnhancedInstance() { - @Override - public Object getSkyWalkingDynamicField() { - return null; - } - - @Override - public void setSkyWalkingDynamicField(Object value) { - - } - }; - - private EnhancedInstance objectInstanceWithSnapshot = new EnhancedInstance() { - @Override - public Object getSkyWalkingDynamicField() { - return contextSnapshot; - } - - @Override - public void setSkyWalkingDynamicField(Object value) { - - } - }; - - @Before - public void setUp() { - interceptor = new CompleteListenerInterceptor(); - when(result.getResponse()).thenReturn(httpResponse); - when(httpRequest.getURI()).thenReturn(URI.create("http://localhost:8080/test")); - when(result.getRequest()).thenReturn(httpRequest); - allArguments = new Object[] {result}; - argumentTypes = new Class[] {result.getClass()}; - when(contextSnapshot.isValid()).thenReturn(true); - when(contextSnapshot.getEntryApplicationInstanceId()).thenReturn(1); - when(contextSnapshot.getSpanId()).thenReturn(2); - when(contextSnapshot.getTraceSegmentId()).thenReturn(mock(ID.class)); - when(contextSnapshot.getDistributedTraceId()).thenReturn(mock(DistributedTraceId.class)); - when(contextSnapshot.getEntryOperationName()).thenReturn("1"); - when(contextSnapshot.getParentOperationName()).thenReturn("2"); - } - - @Test - public void testMethodAroundWithoutSnapshot() throws Throwable { - interceptor.beforeMethod(objectInstanceWithoutSnapshot, null, allArguments, argumentTypes, null); - interceptor.afterMethod(objectInstanceWithoutSnapshot, null, allArguments, argumentTypes, null); - assertThat(segmentStorage.getTraceSegments().size(), is(0)); - } - - @Test - public void testMethodAroundWithSnapshot() throws Throwable { - HttpFields fields = new HttpFields(); - when(httpResponse.getHeaders()).thenReturn(fields); - interceptor.beforeMethod(objectInstanceWithSnapshot, null, allArguments, argumentTypes, null); - interceptor.afterMethod(objectInstanceWithSnapshot, null, allArguments, argumentTypes, null); - - assertThat(segmentStorage.getTraceSegments().size(), is(1)); - TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); - assertThat(traceSegment.getRefs().size(), is(1)); - } -} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java index cddb0b7a7ab46b577ad463ce075bb8ce285226bb..625e2d059269244ea0fd3e837485b7ed1167564c 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java @@ -63,7 +63,7 @@ public class SyncHttpRequestSendInterceptorTest { private Object[] allArguments; private Class[] argumentTypes; private MockHttpRequest enhancedInstance; - private AsyncHttpRequestSendInterceptor interceptor; + private SyncHttpRequestSendInterceptor interceptor; private URI uri = URI.create("http://localhost:8080/test"); @Before @@ -72,7 +72,7 @@ public class SyncHttpRequestSendInterceptorTest { allArguments = new Object[] {"OperationKey", "OperationValue"}; argumentTypes = new Class[] {String.class, String.class}; - interceptor = new AsyncHttpRequestSendInterceptor(); + interceptor = new SyncHttpRequestSendInterceptor(); allArguments = new Object[] {callBackEnhanceInstance}; } diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/MongoDBMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/MongoDBMethodInterceptor.java index ae40d5218abcaf9cb7e61f381b167c862e3e1d23..53a5bbf31ec3ab6d45bd373317c38b0da831ac1b 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/MongoDBMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/MongoDBMethodInterceptor.java @@ -173,7 +173,7 @@ public class MongoDBMethodInterceptor implements InstanceMethodsAroundIntercepto String executeMethod = arguments[0].getClass().getSimpleName(); String remotePeer = (String)objInst.getSkyWalkingDynamicField(); - AbstractSpan span = ContextManager.createExitSpan(MONGO_DB_OP_PREFIX + method.getName(), new ContextCarrier(), remotePeer); + AbstractSpan span = ContextManager.createExitSpan(MONGO_DB_OP_PREFIX + executeMethod, new ContextCarrier(), remotePeer); span.setComponent(ComponentsDefine.MONGODB); Tags.DB_TYPE.set(span, DB_TYPE); SpanLayer.asDB(span); diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/MongoDBMethodInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/MongoDBMethodInterceptorTest.java index adc7798a117e6ad88774dc8cb5c2d305e4aeeb7a..8a88d79e30beebe2827687790f9f75ba5a6ab6e2 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/MongoDBMethodInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/MongoDBMethodInterceptorTest.java @@ -122,7 +122,7 @@ public class MongoDBMethodInterceptorTest { } private void assertRedisSpan(AbstractTracingSpan span) { - assertThat(span.getOperationName(), is("MongoDB/getUsedDatabases")); + assertThat(span.getOperationName(), is("MongoDB/FindOperation")); assertThat(SpanHelper.getComponentId(span), is(9)); List tags = SpanHelper.getTags(span); assertThat(tags.get(1).getValue(), is("FindOperation { \"name\" : \"by\" }")); diff --git a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/define/DriverInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/define/DriverInstrumentation.java index bea877b05ff2cabfaf5bf5ff64a132c9c5b08e5a..27b38e1746f564e0071f6a2b504279d8d85ea2a3 100644 --- a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/define/DriverInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/define/DriverInstrumentation.java @@ -32,6 +32,6 @@ import static org.apache.skywalking.apm.plugin.jdbc.mysql.define.MultiClassNameM public class DriverInstrumentation extends AbstractDriverInstrumentation { @Override protected ClassMatch enhanceClass() { - return byMultiClassMatch("com.mysql.jdbc.Driver", "com.mysql.cj.jdbc.Driver"); + return byMultiClassMatch("com.mysql.jdbc.Driver", "com.mysql.cj.jdbc.Driver", "com.mysql.jdbc.NonRegisteringDriver"); } } diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/AsyncCallInterceptor.java b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/AsyncCallInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..1ae84ef10eae9bee8aa732d6a5594b3910b72277 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/AsyncCallInterceptor.java @@ -0,0 +1,106 @@ +/* + * 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.apm.plugin.okhttp.v3; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import okhttp3.Headers; +import okhttp3.HttpUrl; +import okhttp3.Request; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; + +/** + * {@link AsyncCallInterceptor} get the `EnhanceRequiredInfo` instance from `SkyWalkingDynamicField` and then put it + * into `AsyncCall` instance when the `AsyncCall` constructor called. + * + * {@link AsyncCallInterceptor} also create an exit span by using the `EnhanceRequiredInfo` when the `execute` method + * called. + * + * @author zhangxin + */ +public class AsyncCallInterceptor implements InstanceConstructorInterceptor, InstanceMethodsAroundInterceptor { + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + /** + * The first argument of constructor is not the `real` parameter when the enhance class is an inner class. This + * is the JDK compiler mechanism. + */ + EnhancedInstance realCallInstance = (EnhancedInstance)allArguments[1]; + Object enhanceRequireInfo = realCallInstance.getSkyWalkingDynamicField(); + + objInst.setSkyWalkingDynamicField(enhanceRequireInfo); + } + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + EnhanceRequiredInfo enhanceRequiredInfo = (EnhanceRequiredInfo)objInst.getSkyWalkingDynamicField(); + Request request = (Request)enhanceRequiredInfo.getRealCallEnhance().getSkyWalkingDynamicField(); + + + HttpUrl requestUrl = request.url(); + AbstractSpan span = ContextManager.createExitSpan(requestUrl.uri().getPath(), requestUrl.host() + ":" + requestUrl.port()); + ContextManager.continued(enhanceRequiredInfo.getContextSnapshot()); + ContextCarrier contextCarrier = new ContextCarrier(); + ContextManager.inject(contextCarrier); + span.setComponent(ComponentsDefine.OKHTTP); + Tags.HTTP.METHOD.set(span, request.method()); + Tags.URL.set(span, requestUrl.uri().toString()); + SpanLayer.asHttp(span); + + Field headersField = Request.class.getDeclaredField("headers"); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(headersField, headersField.getModifiers() & ~Modifier.FINAL); + + headersField.setAccessible(true); + Headers.Builder headerBuilder = request.headers().newBuilder(); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + headerBuilder.add(next.getHeadKey(), next.getHeadValue()); + } + headersField.set(request, headerBuilder.build()); + + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/EnhanceRequiredInfo.java b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/EnhanceRequiredInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..ff8a4664b0725460e28b4a84d89dff154f54c478 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/EnhanceRequiredInfo.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.okhttp.v3; + +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +/** + * {@link EnhanceRequiredInfo} storage the `ContextSnapshot` and `RealCall` instances for support the async function of + * okhttp client. + * + * @author zhangxin + */ +public class EnhanceRequiredInfo { + private ContextSnapshot contextSnapshot; + private EnhancedInstance realCallEnhance; + + public EnhanceRequiredInfo(EnhancedInstance realCallEnhance, + ContextSnapshot contextSnapshot) { + this.contextSnapshot = contextSnapshot; + this.realCallEnhance = realCallEnhance; + } + + public ContextSnapshot getContextSnapshot() { + return contextSnapshot; + } + + public EnhancedInstance getRealCallEnhance() { + return realCallEnhance; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/EnqueueInterceptor.java b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/EnqueueInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..63884651f5f9b7a9f7f1ecb62e0841f7ed27c410 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/EnqueueInterceptor.java @@ -0,0 +1,72 @@ +/* + * 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.apm.plugin.okhttp.v3; + +import java.lang.reflect.Method; +import okhttp3.Request; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; + +/** + * {@link EnqueueInterceptor} create a local span and the prefix of the span operation name is start with `Async` when + * the `enqueue` method called and also put the `ContextSnapshot` and `RealCall` instance into the + * `SkyWalkingDynamicField`. + * + * @author zhangxin + */ +public class EnqueueInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + EnhancedInstance callbackInstance = (EnhancedInstance)allArguments[0]; + Request request = (Request)objInst.getSkyWalkingDynamicField(); + ContextManager.createLocalSpan("Async" + request.url().uri().getPath()); + + /** + * Here is the process about how to trace the async function. + * + * 1. Storage `Request` object into `RealCall` instance when the constructor of `RealCall` called. + * 2. Put the `RealCall` instance to `CallBack` instance + * 3. Get the `RealCall` instance from `CallBack` and then Put the `RealCall` into `AsyncCall` instance + * since the constructor of `RealCall` called. + * 5. Create the exit span by using the `RealCall` instance when `AsyncCall` method called. + */ + + callbackInstance.setSkyWalkingDynamicField(new EnhanceRequiredInfo(objInst, ContextManager.capture())); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } + + @Override public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + objInst.setSkyWalkingDynamicField(allArguments[1]); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/OnFailureInterceptor.java similarity index 54% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java rename to apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/OnFailureInterceptor.java index 490be9d749b5edaee78f5d46a6589def1fb63b5d..9b6d357a30d6202554db960bfe3b9d3cfc4468aa 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/OnFailureInterceptor.java @@ -16,51 +16,24 @@ * */ - -package org.apache.skywalking.apm.plugin.jetty.v9.client; +package org.apache.skywalking.apm.plugin.okhttp.v3; import java.lang.reflect.Method; -import org.apache.skywalking.apm.agent.core.context.ContextCarrier; -import org.apache.skywalking.apm.agent.core.context.tag.Tags; -import org.eclipse.jetty.client.HttpRequest; -import org.eclipse.jetty.http.HttpFields; -import org.apache.skywalking.apm.agent.core.context.CarrierItem; import org.apache.skywalking.apm.agent.core.context.ContextManager; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; -import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; - -public class AsyncHttpRequestSendInterceptor implements InstanceMethodsAroundInterceptor { +public class OnFailureInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { - HttpRequest request = (HttpRequest)objInst; - ContextCarrier contextCarrier = new ContextCarrier(); - AbstractSpan span = ContextManager.createExitSpan(request.getURI().getPath(), contextCarrier, request.getHost() + ":" + request.getPort()); - span.setComponent(ComponentsDefine.JETTY_CLIENT); - Tags.HTTP.METHOD.set(span, request.getMethod().asString()); - Tags.URL.set(span, request.getURI().toString()); - SpanLayer.asHttp(span); - - CarrierItem next = contextCarrier.items(); - HttpFields field = request.getHeaders(); - while (next.hasNext()) { - next = next.next(); - field.add(next.getHeadKey(), next.getHeadValue()); - } - - EnhancedInstance callBackResult = (EnhancedInstance)allArguments[0]; - callBackResult.setSkyWalkingDynamicField(ContextManager.capture()); + ContextManager.activeSpan().errorOccurred(); } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { - ContextManager.stopSpan(); return ret; } diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptor.java b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/OnResponseInterceptor.java similarity index 55% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptor.java rename to apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/OnResponseInterceptor.java index 677fbff997c50e7afaf1446bd7173f05e735aa2b..c7c0f390c37c17dfa4028dc612becf36cf2aa2ca 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/OnResponseInterceptor.java @@ -16,48 +16,35 @@ * */ - -package org.apache.skywalking.apm.plugin.jetty.v9.client; +package org.apache.skywalking.apm.plugin.okhttp.v3; import java.lang.reflect.Method; -import org.apache.skywalking.apm.agent.core.context.tag.Tags; -import org.eclipse.jetty.client.api.Result; +import okhttp3.Response; import org.apache.skywalking.apm.agent.core.context.ContextManager; -import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; -import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; -public class CompleteListenerInterceptor implements InstanceMethodsAroundInterceptor { +/** + * {@link OnResponseInterceptor} validate the response code if it is great equal than 400. if so. the transaction status + * chang to `error`, or do nothing. + * + * @author zhangxin + */ +public class OnResponseInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { - ContextSnapshot contextSnapshot = (ContextSnapshot)objInst.getSkyWalkingDynamicField(); - if (contextSnapshot != null) { - Result callBackResult = (Result)allArguments[0]; + Response response = (Response)allArguments[1]; - AbstractSpan abstractSpan = ContextManager.createLocalSpan("CallBack/" + callBackResult.getRequest().getURI().getPath()); - ContextManager.continued(contextSnapshot); - - if (callBackResult.isFailed()) { - abstractSpan.errorOccurred().log(callBackResult.getFailure()); - Tags.STATUS_CODE.set(abstractSpan, Integer.toString(callBackResult.getResponse().getStatus())); - } - abstractSpan.setComponent(ComponentsDefine.JETTY_CLIENT); - abstractSpan.setLayer(SpanLayer.HTTP); + if (response.code() >= 400) { + ContextManager.activeSpan().errorOccurred(); } } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { - ContextSnapshot contextSnapshot = (ContextSnapshot)objInst.getSkyWalkingDynamicField(); - if (contextSnapshot != null) { - ContextManager.stopSpan(); - } return ret; } diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/AsyncCallInstrumentation.java b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/AsyncCallInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..9c802d8acf5864771e15e97639a5c2f48093204a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/AsyncCallInstrumentation.java @@ -0,0 +1,69 @@ +/* + * 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.apm.plugin.okhttp.v3.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class AsyncCallInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override public String getConstructorInterceptor() { + return "org.apache.skywalking.apm.plugin.okhttp.v3.AsyncCallInterceptor"; + } + } + }; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named("execute"); + } + + @Override public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.okhttp.v3.AsyncCallInterceptor"; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName("okhttp3.RealCall$AsyncCall"); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/define/CompleteListenerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/CallbackInstrumentation.java similarity index 62% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/define/CompleteListenerInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/CallbackInstrumentation.java index ee634751313fa9a58c1506c7457c1b5ffe059573..9c791ab47e49d7d6b259328f7759486dca6ca1a2 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/define/CompleteListenerInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/CallbackInstrumentation.java @@ -16,31 +16,19 @@ * */ - -package org.apache.skywalking.apm.plugin.jetty.v9.client.define; +package org.apache.skywalking.apm.plugin.okhttp.v3.define; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import static net.bytebuddy.matcher.ElementMatchers.named; import static org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch; -/** - * {@link CompleteListenerInstrumentation} enhance the onComplete method in all class of hierarchy - * org.eclipse.jetty.client.api.Response$CompleteListener by org.apache.skywalking.apm.plugin.jetty.client.CompleteListenerInterceptor - * - * @author zhangxin - */ -public class CompleteListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { - - private static final String ENHANCE_CLASS = "org.eclipse.jetty.client.api.Response$CompleteListener"; - private static final String ENHANCE_METHOD = "onComplete"; - public static final String SEND_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jetty.client.CompleteListenerInterceptor"; - +public class CallbackInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { return new ConstructorInterceptPoint[0]; } @@ -48,18 +36,28 @@ public class CompleteListenerInstrumentation extends ClassInstanceMethodsEnhance @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { return new InstanceMethodsInterceptPoint[] { new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named(ENHANCE_METHOD); + @Override public ElementMatcher getMethodsMatcher() { + return named("onFailure"); + } + + @Override public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.okhttp.v3.OnFailureInterceptor"; + } + + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named("onResponse"); } - @Override - public String getMethodsInterceptor() { - return SEND_INTERCEPTOR; + @Override public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.okhttp.v3.OnResponseInterceptor"; } - @Override - public boolean isOverrideArgs() { + @Override public boolean isOverrideArgs() { return false; } } @@ -67,6 +65,6 @@ public class CompleteListenerInstrumentation extends ClassInstanceMethodsEnhance } @Override protected ClassMatch enhanceClass() { - return byHierarchyMatch(new String[] {ENHANCE_CLASS}); + return byHierarchyMatch(new String[] {"okhttp3.Callback"}); } } diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/RealCallInstrumentation.java b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/RealCallInstrumentation.java index 8d0bbd6c3e0c19d2204785d1a3329779770fd14c..517b97d4da486b7c78f9143a6bfd4abaf8fc5d2c 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/RealCallInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/RealCallInstrumentation.java @@ -29,6 +29,7 @@ import org.apache.skywalking.apm.plugin.okhttp.v3.RealCallInterceptor; import static net.bytebuddy.matcher.ElementMatchers.any; import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; /** * {@link RealCallInstrumentation} presents that skywalking intercepts {@link okhttp3.RealCall#RealCall(OkHttpClient, @@ -77,6 +78,19 @@ public class RealCallInstrumentation extends ClassInstanceMethodsEnhancePluginDe return INTERCEPT_CLASS; } + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named("enqueue").and(takesArguments(1)); + } + + @Override public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.okhttp.v3.EnqueueInterceptor"; + } + @Override public boolean isOverrideArgs() { return false; } diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/resources/skywalking-plugin.def index dd2eec44540473f0c3026b01130ed113436fbdfe..f9236da8fb7a79d2d394dd248ab259327e9e4f19 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/resources/skywalking-plugin.def @@ -1 +1,3 @@ okhttp-3.x=org.apache.skywalking.apm.plugin.okhttp.v3.define.RealCallInstrumentation +okhttp-3.x=org.apache.skywalking.apm.plugin.okhttp.v3.define.CallbackInstrumentation +okhttp-3.x=org.apache.skywalking.apm.plugin.okhttp.v3.define.AsyncCallInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/concurrent/define/FailureCallbackInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/concurrent/define/FailureCallbackInstrumentation.java index 45fbe6bd8afa82e1ecbee04851b77cb3a17d1719..2c03cc13ec9df93e601635df927b57a4290a81ec 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/concurrent/define/FailureCallbackInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/concurrent/define/FailureCallbackInstrumentation.java @@ -38,7 +38,7 @@ import static org.apache.skywalking.apm.plugin.spring.concurrent.match.FailedCal */ public class FailureCallbackInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { - public static final String FAILURE_CALLBACK_INTERCEPTOR = "FailureCallbackInterceptor"; + public static final String FAILURE_CALLBACK_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.concurrent.FailureCallbackInterceptor"; public static final String FAILURE_METHOD_NAME = "onFailure"; @Override diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/concurrent/define/SuccessCallbackInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/concurrent/define/SuccessCallbackInstrumentation.java index 5659c6277be553909180557f1341ff225fe8742f..a66ed1612272b9958c6f654e1a99aedbbfd9e7a2 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/concurrent/define/SuccessCallbackInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/concurrent/define/SuccessCallbackInstrumentation.java @@ -38,7 +38,7 @@ import static org.apache.skywalking.apm.plugin.spring.concurrent.match.SuccessCa public class SuccessCallbackInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { public static final String SUCCESS_CALLBACK_INTERCEPTOR = - "SuccessCallbackInterceptor"; + "org.apache.skywalking.apm.plugin.spring.concurrent.SuccessCallbackInterceptor"; public static final String SUCCESS_METHOD_NAME = "onSuccess"; @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/resttemplate/async/RestExecuteInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/resttemplate/async/RestExecuteInterceptor.java index ce3f7e5d431888cd22ae920e83cb57241fd7ea7a..f6148968c374192cdfe7af6369f25a0ddf1ad015 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/resttemplate/async/RestExecuteInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/resttemplate/async/RestExecuteInterceptor.java @@ -16,7 +16,6 @@ * */ - package org.apache.skywalking.apm.plugin.spring.resttemplate.async; import java.lang.reflect.Method; @@ -40,7 +39,8 @@ public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor final URI requestURL = (URI)allArguments[0]; final HttpMethod httpMethod = (HttpMethod)allArguments[1]; final ContextCarrier contextCarrier = new ContextCarrier(); - String remotePeer = requestURL.getHost() + ":" + requestURL.getPort(); + + String remotePeer = requestURL.getHost() + ":" + (requestURL.getPort() > 0 ? requestURL.getPort() : "https".equalsIgnoreCase(requestURL.getScheme()) ? 443 : 80); AbstractSpan span = ContextManager.createExitSpan(requestURL.getPath(), contextCarrier, remotePeer); span.setComponent(ComponentsDefine.SPRING_REST_TEMPLATE); diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/resttemplate/sync/RestExecuteInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/resttemplate/sync/RestExecuteInterceptor.java index 3d5088f3efc0fb875f61a2205e166dce0f05bdbc..f634df071d6d291baa2e8711d57fffdef037bee2 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/resttemplate/sync/RestExecuteInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/resttemplate/sync/RestExecuteInterceptor.java @@ -16,7 +16,6 @@ * */ - package org.apache.skywalking.apm.plugin.spring.resttemplate.sync; import java.lang.reflect.Method; @@ -40,7 +39,8 @@ public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor final URI requestURL = (URI)allArguments[0]; final HttpMethod httpMethod = (HttpMethod)allArguments[1]; final ContextCarrier contextCarrier = new ContextCarrier(); - String remotePeer = requestURL.getHost() + ":" + requestURL.getPort(); + + String remotePeer = requestURL.getHost() + ":" + (requestURL.getPort() > 0 ? requestURL.getPort() : "https".equalsIgnoreCase(requestURL.getScheme()) ? 443 : 80); AbstractSpan span = ContextManager.createExitSpan(requestURL.getPath(), contextCarrier, remotePeer); span.setComponent(ComponentsDefine.SPRING_REST_TEMPLATE); diff --git a/docs/README.md b/docs/README.md index 900c41c81a9e990ef058da05964279b5f3e2bfae..c38355652dc677246f57fcdf36b2fe83eb47663d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,9 +3,6 @@ * Getting Started * [Quick start](en/Quick-start.md) - * [Deploy Standalone mode collector](en/Deploy-collector-in-standalone-mode.md) - * [Deploy Cluster mode collector](en/Deploy-collector-in-cluster-mode.md) - * [Deploy javaagent](en/Deploy-skywalking-agent.md) * [Deploy docker image](en/Deploy-docker-image.md) * [Supported middlewares, frameworks and libraries](Supported-list.md) * [How to disable plugins?](en/How-to-disable-plugin.md) @@ -21,6 +18,9 @@ * [Plugin Test](https://github.com/SkywalkingTest/agent-integration-test-report) * [Java Agent Performance Test](https://skywalkingtest.github.io/Agent-Benchmarks/) * Development Guides - * [Skywalking 3 Cross Process Propagation Headers Protocol, v1.0](en/Skywalking-3-Cross-Process-Propagation-Headers-Protocol.md) + * [How to build project](en/How-to-build.md) + * [Plugin development guide](en/Plugin-Development-Guide.md) + * Protocol + * [Cross Process Propagation Headers Protocol, v1.0](en/Skywalking-Cross-Process-Propagation-Headers-Protocol-v1.md) * FAQ diff --git a/docs/README_ZH.md b/docs/README_ZH.md index d091671896e1a261bf55311d1bbef7ff9d84000f..1db771371b8e7a3257602346a3598d20872bfb6e 100644 --- a/docs/README_ZH.md +++ b/docs/README_ZH.md @@ -3,9 +3,6 @@ * [项目简介](/README_ZH.md) * [快速入门](cn/Quick-start-CN.md) - * [部署单机collector](cn/Deploy-collector-in-standalone-mode-CN.md) - * [部署集群collector](cn/Deploy-collector-in-cluster-mode-CN.md) - * [部署探针Agent](cn/Deploy-skywalking-agent-CN.md) * [部署Collector镜像](cn/Deploy-docker-image.CN.md) * [中间件,框架与类库支持列表](Supported-list.md) * [如何关闭特定插件](cn/How-to-disable-plugin-CN.md) @@ -25,8 +22,9 @@ * 开发指南 * [工程编译指南](cn/How-to-build-CN.md) * [插件开发指南](cn/Plugin-Development-Guide-CN.md) - * [跨进程追踪上下文传递协议](cn/Skywalking-3-Cross-Process-Propagation-Headers-Protocol-CN.md) - * [探针与Collector间网络协议,v3.2+](cn/How-to-communicate-with-the-collector-CN.md) + * 交互协议 + * [Cross Process Propagation Headers Protocol, v1.0 跨进程追踪上下文传递协议](cn/Skywalking-Cross-Process-Propagation-Headers-Protocol-CN-v1.md) + * [SkyWalking Trace Data Protocol 探针与Collector间网络协议](cn/Trace-Data-Protocol-CN.md) * FAQ * [Trace查询有数据,但是没有拓扑图和JVM数据?](cn/FAQ/Why-have-traces-no-others-CN.md) * [加载探针,Console被GRPC日志刷屏](cn/FAQ/Too-many-gRPC-logs-CN.md) diff --git a/docs/cn/Application-toolkit-log4j-1.x-CN.md b/docs/cn/Application-toolkit-log4j-1.x-CN.md index a1dcef0058ec638a49bffea84a0a36279a27e19f..bf4891f7de89cd5e4594757e951a58b277e177ad 100644 --- a/docs/cn/Application-toolkit-log4j-1.x-CN.md +++ b/docs/cn/Application-toolkit-log4j-1.x-CN.md @@ -6,7 +6,6 @@ {project.release.version} ``` -   [ ![Download](https://api.bintray.com/packages/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-log4j-1.x/images/download.svg) ](https://bintray.com/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-log4j-1.x/_latestVersion) * 配置layout ```properties diff --git a/docs/cn/Application-toolkit-log4j-2.x-CN.md b/docs/cn/Application-toolkit-log4j-2.x-CN.md index 33790310bef5d599f93ea057e65fc44e5affbdde..a9c4e51422be8ae992bd228a30bdef68b1e108b0 100644 --- a/docs/cn/Application-toolkit-log4j-2.x-CN.md +++ b/docs/cn/Application-toolkit-log4j-2.x-CN.md @@ -6,7 +6,6 @@ {project.release.version} ``` -   [ ![Download](https://api.bintray.com/packages/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-log4j-2.x/images/download.svg) ](https://bintray.com/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-log4j-2.x/_latestVersion) * 在log4j2.xml中的pattern 配置节,配置`[%traceId]` ```xml diff --git a/docs/cn/Application-toolkit-logback-1.x-CN.md b/docs/cn/Application-toolkit-logback-1.x-CN.md index 0182c28ee691f4dd1f3b35156aca8a5fbf11906c..a82ef1e25defd55eee1617e002fda3738bdf9030 100644 --- a/docs/cn/Application-toolkit-logback-1.x-CN.md +++ b/docs/cn/Application-toolkit-logback-1.x-CN.md @@ -6,7 +6,6 @@ {project.release.version} ``` -   [ ![Download](https://api.bintray.com/packages/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-log4j-2.x/images/download.svg) ](https://bintray.com/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-log4j-2.x/_latestVersion) * 在logback.xml中的`Pattern`配制节中,设置`%tid` ```xml diff --git a/docs/cn/Application-toolkit-trace-CN.md b/docs/cn/Application-toolkit-trace-CN.md index 840690909c9622088672a59e0ce952d9aa900493..dab3f7ea4e05400ee83c46d9e5cda87b0237946c 100644 --- a/docs/cn/Application-toolkit-trace-CN.md +++ b/docs/cn/Application-toolkit-trace-CN.md @@ -6,7 +6,6 @@ ${skywalking.version} ``` -   [ ![Download](https://api.bintray.com/packages/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-trace/images/download.svg) ](https://bintray.com/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-trace/_latestVersion) * 随时使用 `TraceContext.traceId()` API,在应用程序的任何地方获取traceId. ```java diff --git a/docs/cn/How-to-build-CN.md b/docs/cn/How-to-build-CN.md index df5fbb0203f14ba9b1ecfd8c478298b038429f6d..8159b1746476dd10b1df43a2fea265350ad92531 100644 --- a/docs/cn/How-to-build-CN.md +++ b/docs/cn/How-to-build-CN.md @@ -2,17 +2,17 @@ 本文档用于指导开发者,在本地开发环境中编译工程。 ### 前言 -因为工程结构和代码依赖会随版本变化,如果读者熟悉travis-ci,则可直接参考[.travis.yml](https://github.com/wu-sheng/sky-walking/blob/master/.travis.yml) +因为工程结构和代码依赖会随版本变化,如果读者熟悉travis-ci,则可直接参考[.travis.yml](../../.travis.yml) ### 编译步骤 1. 准备环境,jdk8,Maven 1. 执行`mvn clean package` +1. 生成包在`/packages`目录下,包括一个`skywalking-agent`的探针目录,以及两个collector包(.tar.gz是linux环境,.zip是windows环境) ### 在IntelliJ IDEA中编译工程 上述步骤在命令行中,能够很好的编译工程,但导入到编译器中的工程依然会有一些报错,我们需要进行几步简单的操作。 1. 在IntelliJ Terminal中,执行`mvn compile -Dmaven.test.skip=true`进行编译 1. 设置gRPC的自动生成代码目录,为源码目录 - - **apm-network/target/generated--sources/protobuf**目录下的`grpc-java`和`java`目录 + - **apm-protocol/apm-network/target/generated-sources/protobuf**目录下的`grpc-java`和`java`目录 - **apm-collector/apm-collector-remote/apm-remote-grpc-provider/target/protobuf**目录下的`grpc-java`和`java`目录 -注:从3.2开始,网络通讯协议引入GRPC,所以增加上述的步骤 diff --git a/docs/cn/How-to-communicate-with-the-collector-CN.md b/docs/cn/How-to-communicate-with-the-collector-CN.md deleted file mode 100644 index 115480d665cdfc52d7b1522f259d020081db9975..0000000000000000000000000000000000000000 --- a/docs/cn/How-to-communicate-with-the-collector-CN.md +++ /dev/null @@ -1,352 +0,0 @@ -# 探针与Collector间通讯协议 -## 前言 -这篇文章主要介绍3.2版本的Collector对外提供的服务协议。一般情况下,使用者和开发者都无需了解此协议细节。但是在庞大的开源生态中,我们已经收到过多次有公司或个人的使用案例,使用自己的非Java探针(PHP,GO等)探针,接入我们的Collector进行数据分析和监控。 - -## 协议类型 -Collector从3.2开始,对外同时提供gRPC和HTTP RESTFul两种类型的协议。从效率上,我们推荐使用gRPC - -# gRPC服务 -本章节,描述官方java探针使用的网络协议 - -## Collector服务发现协议 -### 简介 -**Collector服务发现协议是探针启动时,第一个调用的服务。**通过服务,查找对应的gRPC服务地址与端口列表,并在由客户端选择其中任意一个作为服务端。此服务需周期性调用,确保探针本地的服务端口列表是准确有效的。 - -### 协议类型 -HTTP GET - -### 协议内容 -- 请求 -GET操作:http://collectorIp:port/agentstream/grpc 。 其中`/agentstream/grpc`是默认值,如需修改,需要参考collector相关配置。 - -- 返回 -JSON数组,数组的每个元素,为一个有效的gRPC服务地址。 -```json -["ip address1:port1","ip address2:port2","ip address3:port3"] -``` - -## 应用注册服务 -### 简介 -应用注册服务,是将手动设计的applicationCode,以及ip:port沟通的服务地址,转换成数字的服务。此服务会在后续的传输过程中,有效降低网络带宽需求。 - -### 协议类型 -gRPC服务 - -### 协议内容 -https://github.com/apache/incubator-skywalking/blob/master/apm-network/src/main/proto/ApplicationRegisterService.proto -```proto -syntax = "proto3"; - -option java_multiple_files = true; -option java_package = "org.apache.skywalking.apm.network.proto"; - -import "KeyWithIntegerValue.proto"; - -//register service for ApplicationCode, this service is called when service starts. -service ApplicationRegisterService { - rpc register (Application) returns (ApplicationMapping) { - } -} - -message Application { - repeated string applicationCode = 1; -} - -message ApplicationMapping { - repeated KeyWithIntegerValue application = 1; -} -``` -- 首次调用时,applicationCode为客户端设置的应用名(显示在拓扑图和应用列表上的名字)。之后随着追踪过程,会上报此应用相关的周边服务的`ip:port`地址列表 -- KeyWithIntegerValue 返回,key为上报的applicationCode和ip:port地址,value为对应的id。applicationCode对应的返回id,在后续协议中,被称为applicationId。 -- 此服务按需调用,本地无法找到ip:port对应的id时,可异步发起调用。 -- 获取applicationId的操作是必选。 -- 获取ip:port对应的id是可选,但是完成id设置,会有效提高collector处理效率,降低网络消耗。 - - -## 应用实例发现服务 -### 简介 -应用实例发现服务存在三个子服务,分别是实例注册服务,实例心跳服务,实例注册重连服务。这三个服务负责获取和保持应用实例在线的功能。 - -### 协议类型 -gRPC服务 - -### 实例注册服务 -https://github.com/apache/incubator-skywalking/blob/master/apm-network/src/main/proto/DiscoveryService.proto#L11-L12 -```proto -service InstanceDiscoveryService { - rpc register (ApplicationInstance) returns (ApplicationInstanceMapping) { - } -} - -message ApplicationInstance { - int32 applicationId = 1; - string agentUUID = 2; - int64 registerTime = 3; - OSInfo osinfo = 4; -} - -message OSInfo { - string osName = 1; - string hostname = 2; - int32 processNo = 3; - repeated string ipv4s = 4; -} - -message ApplicationInstanceMapping { - int32 applicationId = 1; - int32 applicationInstanceId = 2; -} -``` -- agentUUID 由探针生成,需保持唯一性,推荐使用UUID算法。并在应用重启前保持不变 -- applicationId 由**应用注册服务**获取。 -- 服务端返回应用实例id,applicationInstanceId 。后续上报服务使用实例id标识。 - -### 实例心跳服务 -https://github.com/apache/incubator-skywalking/blob/master/apm-network/src/main/proto/DiscoveryService.proto#L14-L15 -```proto -service InstanceDiscoveryService { - rpc heartbeat (ApplicationInstanceHeartbeat) returns (Downstream) { - } -} - -message ApplicationInstanceHeartbeat { - int32 applicationInstanceId = 1; - int64 heartbeatTime = 2; -} -``` -- 心跳服务每分钟上报一次。 -- 如一分钟内有segment数据上报,则可不必上报心跳。 - -### 实例注册重连服务 -https://github.com/apache/incubator-skywalking/blob/master/apm-network/src/main/proto/DiscoveryService.proto#L17-L18 -```proto -service InstanceDiscoveryService { - rpc registerRecover (ApplicationInstanceRecover) returns (Downstream) { - } -} - -message ApplicationInstanceRecover { - int32 applicationId = 1; - int32 applicationInstanceId = 2; - int64 registerTime = 3; - OSInfo osinfo = 4; -} -``` -- 应用重连服务于**应用注册服务**类似,在gRPC发生重连,并再次连接成功后发送。需包含通过**应用注册服务**获取的applicationInstanceId。 - -## 服务名注册发现服务 -### 简介 -服务名注册发现服务,是将应用内的服务名(operationName)替换为id的服务。 - -### 协议类型 -gRPC服务 - -### 协议内容 -https://github.com/apache/incubator-skywalking/blob/master/apm-network/src/main/proto/DiscoveryService.proto#L53-L74 -```proto -//discovery service for ServiceName by Network address or application code -service ServiceNameDiscoveryService { - rpc discovery (ServiceNameCollection) returns (ServiceNameMappingCollection) { - } -} - -message ServiceNameCollection { - repeated ServiceNameElement elements = 1; -} - -message ServiceNameMappingCollection { - repeated ServiceNameMappingElement elements = 1; -} - -message ServiceNameMappingElement { - int32 serviceId = 1; - ServiceNameElement element = 2; -} - -message ServiceNameElement { - string serviceName = 1; - int32 applicationId = 2; -} -``` -- 可选服务,可有效降低网络消耗,推荐实现。注意,由于部分应用存在URI中夹带参数的情况,请注意限制探针内的缓存容量,防止内存溢出。 -- ServiceNameElement中,applicationId为当前applicationCode对应的id。serviceName一般为对应span的operationName - -## JVM指标上报服务 -### 简介 -上报当前实例的JVM信息,每秒上报一次。 - -### 协议类型 -gRPC服务 - -### 协议内容 -https://github.com/apache/incubator-skywalking/blob/master/apm-network/src/main/proto/JVMMetricsService.proto -```proto -syntax = "proto3"; - -option java_multiple_files = true; -option java_package = "org.apache.skywalking.apm.network.proto"; - -import "Downstream.proto"; - -service JVMMetricsService { - rpc collect (JVMMetrics) returns (Downstream) { - } -} - -message JVMMetrics { - repeated JVMMetric metrics = 1; - int64 applicationInstanceId = 2; -} - -message JVMMetric { - int64 time = 1; - CPU cpu = 2; - repeated Memory memory = 3; - repeated MemoryPool memoryPool = 4; - repeated GC gc = 5; -} - -message CPU { - double usagePercent = 2; -} - -message Memory { - bool isHeap = 1; - int64 init = 2; - int64 max = 3; - int64 used = 4; - int64 committed = 5; -} - -message MemoryPool { - PoolType type = 1; - bool isHeap = 2; - int64 init = 3; - int64 max = 4; - int64 used = 5; - int64 commited = 6; -} - -enum PoolType { - CODE_CACHE_USAGE = 0; - NEWGEN_USAGE = 1; - OLDGEN_USAGE = 2; - SURVIVOR_USAGE = 3; - PERMGEN_USAGE = 4; - METASPACE_USAGE = 5; -} - -message GC { - GCPhrase phrase = 1; - int64 count = 2; - int64 time = 3; -} - -enum GCPhrase { - NEW = 0; - OLD = 1; -} -``` - -## TraceSegment上报服务 -### 简介 -上报调用链信息 - -### 协议类型 -gRPC服务 - -### 协议内容 -```proto -syntax = "proto3"; - -option java_multiple_files = true; -option java_package = "org.apache.skywalking.apm.network.proto"; - -import "Downstream.proto"; -import "KeyWithStringValue.proto"; - -service TraceSegmentService { - rpc collect (stream UpstreamSegment) returns (Downstream) { - } -} - -message UpstreamSegment { - repeated UniqueId globalTraceIds = 1; - bytes segment = 2; // the byte array of TraceSegmentObject -} - -message UniqueId { - repeated int64 idParts = 1; -} - -message TraceSegmentObject { - UniqueId traceSegmentId = 1; - repeated TraceSegmentReference refs = 2; - repeated SpanObject spans = 3; - int32 applicationId = 4; - int32 applicationInstanceId = 5; -} - -message TraceSegmentReference { - RefType refType = 1; - UniqueId parentTraceSegmentId = 2; - int32 parentSpanId = 3; - int32 parentApplicationInstanceId = 4; - string networkAddress = 5; - int32 networkAddressId = 6; - string entryServiceName = 7; - int32 entryServiceId = 8; - string parentServiceName = 9; - int32 parentServiceId = 10; -} - -message SpanObject { - int32 spanId = 1; - int32 parentSpanId = 2; - int64 startTime = 3; - int64 endTime = 4; - int32 operationNameId = 5; - string operationName = 6; - int32 peerId = 7; - string peer = 8; - SpanType spanType = 9; - SpanLayer spanLayer = 10; - int32 componentId = 11; - string component = 12; - bool isError = 13; - repeated KeyWithStringValue tags = 14; - repeated LogMessage logs = 15; -} - -enum RefType { - CrossProcess = 0; - CrossThread = 1; -} - -enum SpanType { - Entry = 0; - Exit = 1; - Local = 2; -} - -enum SpanLayer { - Database = 0; - RPCFramework = 1; - Http = 2; - MQ = 3; -} - -message LogMessage { - int64 time = 1; - repeated KeyWithStringValue data = 2; -} -``` -- UniqueId为segment或者globalTraceId的数字表示。由3个long组成,1)applicationInstanceId,2)当前线程id,3)当前时间戳*10000 + seq(0-10000自循环) -- Span的数据,请参考[插件开发规范](https://github.com/apache/incubator-skywalking/wiki/Plugin-Development-Guide) -- 以下id和名称根据注册返回结果,优先上报id,无法获取id时,再上传name。参考之前的应用和服务注册章节。 - - operationNameId/operationName - - networkAddress/networkAddressId - - entryServiceName/entryServiceId - - parentServiceName/parentServiceId - - peerId/peer -- componentId为默认支持的插件id,非官方支持,需传输名称或修改服务端源代码。[官方组件列表](../../apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java) diff --git a/docs/cn/Plugin-Development-Guide-CN.md b/docs/cn/Plugin-Development-Guide-CN.md index b0e306e688d0efe21d04564eabf9ddb6da830e1d..83f19305ef742c8d1838d6e24861adbaec527b3b 100644 --- a/docs/cn/Plugin-Development-Guide-CN.md +++ b/docs/cn/Plugin-Development-Guide-CN.md @@ -1,10 +1,11 @@ ## 插件开发指南 -本文档描述 [v3.2+](https://github.com/OpenTracing/skywalking/releases) 插件开发方法、使用的API,以及注意事项。 +这边文档描述插件的开发和贡献方法 -### 核心概念 -#### 一. Span +## 核心概念 +### 一. Span Span是追踪系统中的通用概念(有时候被翻译成埋点),关于Span的定义,请参考[OpenTracing 中文版](https://github.com/opentracing-contrib/opentracing-specification-zh/blob/master/specification.md#opentracing数据模型)。 -sky-walking作为OpenTracing的支持者,在核心实现中,与标准有较高的相似度。 + +SkyWalking作为OpenTracing的支持者,在核心实现中,与标准有较高的相似度。当然,作为实际产品的需要,我们一会扩展相关概念。 我们将span分为三类: @@ -15,16 +16,19 @@ EntrySpan代表一个服务的提供方,即,服务端的入口点。它是 LocalSpan代表一个普通的Span,代表任意一个本地逻辑块(或方法) 1.3 ExitSpan -ExitSpan也可以称为LeafSpan(sky-walking的早期版本中的称呼),代表了一个远程服务的客户端调用。如:一次JDBC调用。 +ExitSpan也可以称为LeafSpan(SkyWalking的早期版本中的称呼),代表了一个远程服务的客户端调用。如:一次JDBC调用。 -#### 二. ContextCarrier -分布式追踪要解决的一个重要问题,就是跨进程的问题,ContextCarrier的概念就是为了解决这种场景。 +### 二. ContextCarrier +分布式追踪要解决的一个重要问题,就是跨进程调用链连接的问题,ContextCarrier的概念就是为了解决这种场景。 当发生一次**A->B**的网络调用时: -1. 需要在客户端生成(inject操作)ContextCarrier,并序列化成String -1. 将这个String加入RPC调用的正文(或HEAD)中,传递到服务端 +1. 创建一个空的ContextCarrier +1. 通过`ContextManager#createExitSpan`方法创建一个ExitSpan,或者使用`ContextManager#inject`,在过程中传入并初始化`ContextCarrier` +1. 将`ContextCarrier`中所有元素放入请求头(如:HTTP头)或消息正文(如 Kafka) +1. `ContextCarrier`随请求传输到服务端 1. 服务端收到后,转换为新的ContextCarrier -1. 通过提取操作(extract操作)建立关联 +1. 通过`ContestManager#createEntrySpan`方法创建EntrySpan,或者使用`ContextManager#extract`,建立分布式调用关联 + 以HTTPComponent调用Tomcat为例: 1. 客户端(HTTPComponent端) @@ -33,8 +37,7 @@ ExitSpan也可以称为LeafSpan(sky-walking的早期版本中的称呼),代表 CarrierItem next = contextCarrier.items(); while (next.hasNext()) { next = next.next(); - //向HTTP或者其他RPC HEAD中设置上下文 - heads.put(next.getHeadKey(), next.getHeadValue()); + httpRequest.setHeader(next.getHeadKey(), next.getHeadValue()); } ``` @@ -44,23 +47,23 @@ ExitSpan也可以称为LeafSpan(sky-walking的早期版本中的称呼),代表 CarrierItem next = contextCarrier.items(); while (next.hasNext()) { next = next.next(); - //从HTTP或者其他RPC HEAD中,根据指定的KEY,提取上下文 - next.setHeadValue(heads.get(next.getHeadKey())); + next.setHeadValue(request.getHeader(next.getHeadKey())); } span = ContextManager.createEntrySpan(“/span/operation/name”, contextCarrier); ``` -#### 三. ContextSnapshot -除了跨进程的RPC调用,另外一种追踪的常见场景是跨线程。跨线程和跨进程有很高的相似度,都是需要完成上下文的传递工作。所以ContextSnapshot具有和ContextCarrier十分类似的API风格。 +### 三. ContextSnapshot +除了跨进程的RPC调用,另外一种追踪的常见场景是跨线程保持链路连接。跨线程和跨进程有很高的相似度,都是需要完成上下文的传递工作。 +所以ContextSnapshot具有和ContextCarrier十分类似的API风格。 当发生一次**A->B**的跨线程调用时: 1. 需要在A线程中通过ContextManager#capture操作生成ContextSnapshot对象实例 1. 将这个ContextSnapshot对象传递到B线程中 1. B线程通过ContextManager#continued操作完成上下文传递 -### 核心API -#### 一. ContextManager +## 核心API +### 一. ContextManager ContextManager提供了追踪相关操作的主入口 1. 创建EntrySpan @@ -81,7 +84,7 @@ public static AbstractSpan createExitSpan(String operationName, ContextCarrier c ``` 根据服务名,跨进程传递的ContextCarrier(空容器)和远端服务地址(IP、主机名、域名 + 端口),创建ExitSpan -#### 二. AbstractSpan +### 二. AbstractSpan AbstractSpan提供了Span内部,进行操作的各项API ```java @@ -139,17 +142,21 @@ AbstractSpan提供了Span内部,进行操作的各项API ``` Span的操作语义和OpenTracing类似。 -SpanLayer为我们的特有概念,如果是远程调用类的服务,请设置此属性,包括4个属性值 +SpanLayer为我们的特有概念,如果是远程调用类的服务,请设置此属性,包括5个属性值 +1. UNKNOWN, 默认 1. DB 1. RPC_FRAMEWORK,非HTTP类型的RPC框架,如:原生的DUBBO,MOTAN 1. HTTP 1. MQ -### 开发插件 -#### 一. 简介 -因为所有的程序调用都是基于方法的,所以插件实际上就是基于方法的拦截,类似面向切面编程的AOP技术。sky-walking底层已经完成相关的技术封装,所以插件开发者只需要定位需要拦截的类、方法,然后结合上文中的追踪API,即可完成插件的开发。 +Component ID被SkyWalking项目组定义和保护。0到10000为保留值,如果你希望贡献新插件,可以在插件pull request通过,并提交的自动化 +测试用户被接收后,申请自己的组件ID。私有插件,请使用10000以上的ID,避免重复。 + +## 开发插件 +### 一. 简介 +因为所有的程序调用都是基于方法的,所以插件实际上就是基于方法的拦截,类似面向切面编程的AOP技术。SkyWalking底层已经完成相关的技术封装,所以插件开发者只需要定位需要拦截的类、方法,然后结合上文中的追踪API,即可完成插件的开发。 -#### 二. 拦截类型 +### 二. 拦截类型 根据Java方法,共有三种拦截类型 1. 拦截构造函数 1. 拦截实例方法 @@ -161,7 +168,7 @@ SpanLayer为我们的特有概念,如果是远程调用类的服务,请设 当然,也可以同时支持实例和静态方法,直接继承ClassEnhancePluginDefine。但是,这种情况很少。 -#### 三. 实现自己的插件定义 +### 三. 实现自己的插件定义 我们以继承ClassInstanceMethodsEnhancePluginDefine为例(ClassStaticMethodsEnhancePluginDefine十分类似,不再重复描述),描述定义插件的全过程 1. 定义目标类名称 @@ -169,7 +176,7 @@ SpanLayer为我们的特有概念,如果是远程调用类的服务,请设 protected abstract ClassMatch enhanceClass(); ``` -ClassMatch反应类的匹配方式,目前提供三种: +ClassMatch反应类的匹配方式,目前提供四种: * byName, 通过类名完整匹配 * byClassAnnotationMatch, 通过类标注进行匹配 @@ -190,7 +197,7 @@ protected ClassMatch enhanceClassName() { ``` -2. 定义构造函数拦截点 +2. 定义方法拦截点 ```java protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints(); @@ -221,7 +228,7 @@ tomcat-7.x/8.x=TomcatInstrumentation * 插件名称,要求全局唯一,命名规范:目标组件+版本号 * 插件定义类全名 -#### 四. 实现拦截器逻辑 +### 四. 实现拦截器逻辑 我们继续以实现实例方法拦截为例,拦截器需要实现org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor。 ```java /** @@ -262,15 +269,15 @@ public interface InstanceMethodsAroundInterceptor { 可以在方法执行前、执行后、执行异常三个点,进行拦截,设置修改方法参数(执行前),并调用核心API,设置追踪逻辑。 -### 贡献插件到主仓库 +## 贡献插件到主仓库 我们鼓励大家共同贡献支持各个类库的插件。 大家需支持以下步骤执行: 1. 在issue页面提出插件扩展需求,对应的版本。 -1. Fork wu-sheng/sky-walking到本地 +1. Fork apache/incubator-skywalking到本地 1. 在apm-sniffer/apm-sdk-plugin下新建自己的插件模块,模块名为:支持类库名称+版本号 1. 按照规范开发插件 1. 完善注释和测试用例 1. 在本地打包进行集成测试 -1. 提交Pull Request到 wu-sheng/sky-walking,提供插件追踪的截图(拓扑和Trace明细),可独立运行的被追踪程序、docker镜像或docker-compose。 -1. sky-walking PMC( Project Management Committee) 成员完成插件审核,确定发布版本,并合并到主仓库。 +1. 提交Pull Request到 apache/incubator-skywalking,根据评审团队要求,提供相关自动化测试用例 +1. SkyWalking Committer成员完成插件审核,确定发布版本,并合并到主仓库。 diff --git a/docs/cn/Skywalking-3-Cross-Process-Propagation-Headers-Protocol-CN.md b/docs/cn/Skywalking-Cross-Process-Propagation-Headers-Protocol-CN-v1.md similarity index 81% rename from docs/cn/Skywalking-3-Cross-Process-Propagation-Headers-Protocol-CN.md rename to docs/cn/Skywalking-Cross-Process-Propagation-Headers-Protocol-CN-v1.md index 7c1be77781fc1b087177e967950f27e01b13e86f..88455346716b1862a0bdaf92b4ecc6d223bda0b8 100644 --- a/docs/cn/Skywalking-3-Cross-Process-Propagation-Headers-Protocol-CN.md +++ b/docs/cn/Skywalking-Cross-Process-Propagation-Headers-Protocol-CN-v1.md @@ -1,13 +1,15 @@ -# Skywalking 3 Cross Process Propagation Headers Protocol +# Skywalking Cross Process Propagation Headers Protocol * Version 1.0 -这是Skywalking3跨进程传输头协议第一个公开版本。Skywalking是一个偏向APM的分布式追踪系统,所以,为了提供服务端处理性能。头信息会比其他的追踪系统要更复杂一些。你会发现,这个头信息,更像一个商业APM系统,并且,一些商业APM系统的头信息,比我们的要复杂的多。所以,如果你希望开发或者贡献其他语言探针、或者JAVA探针的其他市县模式,请耐心阅读,并理解此协议内容。 - +Skywalking是一个偏向APM的分布式追踪系统,所以,为了提供服务端处理性能。头信息会比其他的追踪系统要更复杂一些。 +你会发现,这个头信息,更像一个商业APM系统,并且,一些商业APM系统的头信息,比我们的要复杂的多。 # Header Item * Header Name: `sw3` * Header Value: 使用`|`分隔,包含以下内容 +_消息头使用sw3,因为此协议始于SkyWalking 3.x版本。_ + ## Values * Trace Segment Id diff --git a/docs/cn/Trace-Data-Protocol-CN.md b/docs/cn/Trace-Data-Protocol-CN.md new file mode 100644 index 0000000000000000000000000000000000000000..51c9afec9e01b4af61331a534aca71a8da3d2f2d --- /dev/null +++ b/docs/cn/Trace-Data-Protocol-CN.md @@ -0,0 +1,101 @@ +# Trace Data Protocol 中文 +Trace Data Protocol协议,也就是探针与Collector间通讯协议 + +## 概述 +此协议包含了Agent上行/下行数据的格式,可用于定制开发,或者探针的多语言扩展 + +### 协议版本 +v1.1 + +### 协议类型 +* 服务发现使用http服务 +* 注册和数据上行服务同时支持gRPC和HTTP服务 + +#### gRPC协议定义文件 +[gRPC proto files](../../apm-protocol/apm-network/src/main/proto) + +## Collector服务发现协议 +### 简介 +**Collector服务发现协议是探针启动时,第一个调用的服务。** 通过服务,查找可用的gRPC服务地址列表,并在由客户端选择其中任意一个作为服务端。 +此服务建议周期性调用,确保探针本地的服务端口列表是准确有效的。 + +### 协议类型 +HTTP GET + +### 协议内容 +- 请求 +GET操作:http://collectorIp:port/agent/grpc 。 其中`/agent/grpc`是默认值,如需修改,需要参考collector相关配置。 + +- 返回 +JSON数组,数组的每个元素,为一个有效的gRPC服务地址。 +```json +["ip address1:port1","ip address2:port2","ip address3:port3"] +``` + +## 应用注册服务 +### 简介 +应用注册服务,是将applicationCode,以及ip:port构成的服务地址,转换成数字ID的服务。 +此服务会在后续的传输过程中,有效降低网络带宽需求。 + +### 协议内容 +[gRPC service define](../..apm-protocol/apm-network/src/main/proto/ApplicationRegisterService.proto) + +- 首次调用时,applicationCode为客户端设置的应用名(显示在拓扑图和应用列表上的名字)。之后随着追踪过程,会上报此应用相关的周边服务的`ip:port`地址列表 +- KeyWithIntegerValue 返回,key为上报的applicationCode或ip:port地址,value为对应的id。applicationCode对应的返回id,在后续协议中,被称为applicationId。 +- 此服务按需调用,本地无法找到ip:port对应的id时,可异步发起调用。 +- 获取applicationId的操作是必选。后续追踪数据依赖此id +- 获取ip:port对应的id是可选,使用id,会有效提高collector处理效率,降低网络消耗。 + +## 应用实例发现服务 +### 简介 +应用实例发现服务存在三个子服务,分别是实例注册服务,实例心跳服务,实例注册重连服务。这三个服务负责获取和保持应用实例在线的功能。 + +### 协议类型 +gRPC服务 + +### 实例注册服务 +[gRPC service define](../../apm-protocol/apm-network/src/main/proto/DiscoveryService.proto#L11-L12) + +- agentUUID 由探针生成,需保持唯一性,推荐使用UUID算法。并在应用重启前保持不变 +- applicationId 由**应用注册服务**获取。 +- 服务端返回应用实例id,applicationInstanceId 。后续上报服务使用实例id标识。 + +### 实例心跳服务 +[gRPC service define](../../apm-protocol/apm-network/src/main/proto/DiscoveryService.proto#L14-L15) + +- 心跳服务每分钟上报一次。 +- 如果一分钟内有segment数据上报,则可不必上报心跳。 + +## 服务名注册发现服务 +### 简介 +服务名注册发现服务,是将应用内的服务名(operationName)替换为id的服务。 + +### 协议内容 +[gRPC service define](../../apm-protocol/apm-network/src/main/proto/DiscoveryService.proto#L53-L74) + +- 可选服务,可有效降低网络消耗,推荐实现。注意,由于部分应用存在URI中夹带参数的情况,请注意限制探针内的缓存容量,防止内存溢出。 +- ServiceNameElement中,applicationId为当前applicationCode对应的id。serviceName一般为对应span的operationName + +## JVM指标上报服务 +### 简介 +上报当前实例的JVM信息,每秒上报一次。 + +### 协议内容 +[gRPC service define](../../apm-protocol/apm-network/src/main/proto/JVMMetricsService.proto) + +## TraceSegment上报服务 +### 简介 +上报调用链信息 + +### 协议内容 +[gRPC service define](../../apm-protocol/apm-network/src/main/proto/TraceSegmentService.proto) + +- UniqueId为segment或者globalTraceId的数字表示。由3个long组成,1)applicationInstanceId,2)当前线程id,3)当前时间戳*10000 + seq(0-10000自循环) +- Span的数据,请参考[插件开发规范](Plugin-Development-Guide-CN.md) +- 以下id和名称根据注册返回结果,优先上报id,无法获取id时,再上传name。参考之前的应用和服务注册章节。 + - operationNameId/operationName + - networkAddress/networkAddressId + - entryServiceName/entryServiceId + - parentServiceName/parentServiceId + - peerId/peer +- componentId为默认支持的插件id,非官方支持,需传输名称或修改服务端源代码。[官方组件列表](../../apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java) diff --git a/docs/en/Application-toolkit-log4j-1.x.md b/docs/en/Application-toolkit-log4j-1.x.md index 80a37d6904a087fb957727b5f6857544fa16b7f3..753bf4b89445b9fe6aa48647a5d6f406e84902f6 100644 --- a/docs/en/Application-toolkit-log4j-1.x.md +++ b/docs/en/Application-toolkit-log4j-1.x.md @@ -6,7 +6,6 @@ {project.release.version} ``` -   [ ![Download](https://api.bintray.com/packages/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-log4j-1.x/images/download.svg) ](https://bintray.com/wu-sheng/skywalking/org.apache.skywalking.apmg-toolkit-log4j-1.x/_latestVersion) * Config a layout ```properties diff --git a/docs/en/Application-toolkit-log4j-2.x.md b/docs/en/Application-toolkit-log4j-2.x.md index 13fb77e259e1e5e7b8070926264957b14d78bba6..19502f9aec22a60e58fed3cf5e7019b38f10836f 100644 --- a/docs/en/Application-toolkit-log4j-2.x.md +++ b/docs/en/Application-toolkit-log4j-2.x.md @@ -6,7 +6,6 @@ {project.release.version} ``` -   [ ![Download](https://api.bintray.com/packages/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-log4j-2.x/images/download.svg) ](https://bintray.com/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-log4j-2.x/_latestVersion) * Config the `[%traceId]` pattern in your log4j2.xml ```xml diff --git a/docs/en/Application-toolkit-logback-1.x.md b/docs/en/Application-toolkit-logback-1.x.md index 6a52091a2d5fdde7d32876f8aedf85286ffd20bd..4b60043a894e9080bfb89c00b4c0dab3fcfd8065 100644 --- a/docs/en/Application-toolkit-logback-1.x.md +++ b/docs/en/Application-toolkit-logback-1.x.md @@ -6,7 +6,6 @@ {project.release.version} ``` -   [ ![Download](https://api.bintray.com/packages/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-logback-1.x/images/download.svg) ](https://bintray.com/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-logback-1.x/_latestVersion) * set `%tid` in `Pattern` section of logback.xml ```xml diff --git a/docs/en/Application-toolkit-trace.md b/docs/en/Application-toolkit-trace.md index e6dfdae17810a42060d780b56668b4f644510ede..4f195de41cad62c8979665fbec6e9cb660063c02 100644 --- a/docs/en/Application-toolkit-trace.md +++ b/docs/en/Application-toolkit-trace.md @@ -6,7 +6,6 @@ ${skywalking.version} ``` -   [ ![Download](https://api.bintray.com/packages/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-trace/images/download.svg) ](https://bintray.com/wu-sheng/skywalking/org.apache.skywalking.apm-toolkit-trace/_latestVersion) * Use `TraceContext.traceId()` API to obtain traceId. ```java diff --git a/docs/en/Deploy-skywalking-agent.md b/docs/en/Deploy-skywalking-agent.md index d208d8b4cf355af668eeed1f2519cb6aa3c8b7a8..c42ee3b51cba0ef3b87849d8f10167aff78afa92 100644 --- a/docs/en/Deploy-skywalking-agent.md +++ b/docs/en/Deploy-skywalking-agent.md @@ -1,5 +1,5 @@ ## Download skywalking agent release version -- Go to [release page](https://github.com/wu-sheng/sky-walking/releases) +- Go to [release page](https://github.com/apache/incubator-skywalking/releases) ## Deploy skywalking javaagent 1. Copy the agent package to anywhere you like. The logs, plugins and config are all included in the package. @@ -42,5 +42,5 @@ CATALINA_OPTS="$CATALINA_OPTS -javaagent:/path/to/skywalking-agent/skywalking-ag - Tomcat 8 Change the first line of `tomcat/bin/catalina.sh`. ```shell -set "CATALINA_OPTS=... -javaagent:E:\apache-tomcat-8.5.20\skywalking-agent\skywalking-agent.jar -Dconfig=\skywalking\config\dir" +set "CATALINA_OPTS=-javaagent:E:\apache-tomcat-8.5.20\skywalking-agent\skywalking-agent.jar -Dconfig=\skywalking\config\dir" ``` \ No newline at end of file diff --git a/docs/en/How-to-build.md b/docs/en/How-to-build.md new file mode 100644 index 0000000000000000000000000000000000000000..b21e504f85df0fb627f6fcca2d53f8803f629d7f --- /dev/null +++ b/docs/en/How-to-build.md @@ -0,0 +1,14 @@ +# How to build project +This document helps people to compile and build the project in your maven and IDE. + +## Build in maven +1. Prepare JDK8 and maven3 +1. Run `mvn clean package` +1. All packages are in `/packages`, which includes `skywalking-agent` folder, and two collector files(.tar.gz for Linux and .zip for Windows) + +## Setup your IntelliJ IDEA +1. Import the project as a maven project +1. Run `mvn compile -Dmaven.test.skip=true` to compile project and generate source codes. Because we use gRPC and protobuf. +1. Set **Generated Source Codes** folders. + * `grpc-java` and `java` folders in **apm-protocol/apm-network/target/generated-sources/protobuf** + * `grpc-java` and `java` folders in **apm-collector/apm-collector-remote/apm-remote-grpc-provider/target/protobuf** \ No newline at end of file diff --git a/docs/en/Plugin-Development-Guide.md b/docs/en/Plugin-Development-Guide.md new file mode 100644 index 0000000000000000000000000000000000000000..2174c33d6d6d25c5582d5ee86a34074c1da47bed --- /dev/null +++ b/docs/en/Plugin-Development-Guide.md @@ -0,0 +1,290 @@ +# Plugin Development Guide +This document describe how to understand, develop and contribute plugin. + +## Concepts +### Span +Span is an important and common concept in distributed tracing system. Learn **Span** from +[Google Dapper Paper](https://research.google.com/pubs/pub36356.html) and +[OpenTracing](http://opentracing.io) + +SkyWalking supports OpenTracing and OpenTracing-Java API from 2017. Our Span concepts are similar with the paper and OpenTracing. +Also we extend the Span. + +There are three types of Span + +1.1 EntrySpan +EntrySpan represents a service provider, also the endpoint of server side. As an APM system, we are targeting the +application servers. So almost all the services and MQ-comsumer are EntrySpan(s). + +1.2 LocalSpan +LocalSpan represents a normal Java method, which don't relate with remote service, neither a MQ producer/comsumer +nor a service(e.g. HTTP service) provider/consumer. + +1.3 ExitSpan +ExitSpan represents a client of service or MQ-producer, as named as `LeafSpan` at early age of SkyWalking. +e.g. accessing DB by JDBC, reading Redis/Memcached are cataloged an ExitSpan. + +### ContextCarrier +In order to implement distributed tracing, the trace across process need to be bind, and the context should propagate +across the process. That is ContextCarrier's duty. + +Here are the steps about how to use **ContextCarrier** in a `A->B` distributed call. +1. Create a new and empty `ContextCarrier` at client side. +1. Create an ExitSpan by `ContextManager#createExitSpan` or use `ContextManager#inject` to init the `ContextCarrier`. +1. Put all items of `ContextCarrier` into heads(e.g. HTTP HEAD), attachments(e.g. Dubbo RPC framework) or messages(e.g. Kafka) +1. The `ContextCarrier` propagates to server side by the service call. +1. At server side, get all items from heads, attachments or messages. +1. Create an EntrySpan by `ContestManager#createEntrySpan` or use `ContextManager#extract` to bind the client and server. + + +Let's demonstrate the steps by Apache HTTPComponent client plugin and Tomcat 7 server plugin +1. Client side steps by Apache HTTPComponent client plugin +```java + span = ContextManager.createExitSpan("/span/operation/name", contextCarrier, "ip:port"); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + httpRequest.setHeader(next.getHeadKey(), next.getHeadValue()); + } +``` + +2. Server side steps by Tomcat 7 server plugin +```java + ContextCarrier contextCarrier = new ContextCarrier(); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + next.setHeadValue(request.getHeader(next.getHeadKey())); + } + + span = ContextManager.createEntrySpan(“/span/operation/name”, contextCarrier); +``` + +### ContextSnapshot +Besides across process, across thread but in a process need to be supported, because async process(In-memory MQ) +and batch process are common in Java. Across process and across thread are similar, because they are both about propagating +context. The only difference is that, don't need to serialize for across thread. + +Here are the three steps about across thread propagation: +1. Use `ContextManager#capture` to get the ContextSnapshot object. +1. Let the sub-thread access the ContextSnapshot by any way, through method arguments or carried by an existed arguments +1. Use `ContextManager#continued` in sub-thread. + +## Core APIs +### ContextManager +ContextManager provides all major and primary APIs. + +1. Create EntrySpan +```java +public static AbstractSpan createEntrySpan(String operationName, ContextCarrier carrier) +``` +Create EntrySpan by operation name(e.g. service name, uri) and **ContextCarrier**. + +2. Create LocalSpan +```java +public static AbstractSpan createLocalSpan(String operationName) +``` +Create LocalSpan by operation name(e.g. full method signature) + +3. Create ExitSpan +```java +public static AbstractSpan createExitSpan(String operationName, ContextCarrier carrier, String remotePeer) +``` +Create ExitSpan by operation name(e.g. service name, uri) and new **ContextCarrier** and peer address +(e.g. ip+port, hostname+port) + +### AbstractSpan +```java + /** + * Set the component id, which defines in {@link ComponentsDefine} + * + * @param component + * @return the span for chaining. + */ + AbstractSpan setComponent(Component component); + + /** + * Only use this method in explicit instrumentation, like opentracing-skywalking-bridge. + * It it higher recommend don't use this for performance consideration. + * + * @param componentName + * @return the span for chaining. + */ + AbstractSpan setComponent(String componentName); + + AbstractSpan setLayer(SpanLayer layer); + + /** + * Set a key:value tag on the Span. + * + * @return this Span instance, for chaining + */ + AbstractSpan tag(String key, String value); + + /** + * Record an exception event of the current walltime timestamp. + * + * @param t any subclass of {@link Throwable}, which occurs in this span. + * @return the Span, for chaining + */ + AbstractSpan log(Throwable t); + + AbstractSpan errorOccurred(); + + /** + * Record an event at a specific timestamp. + * + * @param timestamp The explicit timestamp for the log record. + * @param event the events + * @return the Span, for chaining + */ + AbstractSpan log(long timestamp, Map event); + + /** + * Sets the string name for the logical operation this span represents. + * + * @return this Span instance, for chaining + */ + AbstractSpan setOperationName(String operationName); +``` +Besides set operation name, tags and logs, two attributes shoule be set, which are component and layer, +especially for EntrySpan and ExitSpan + +SpanLayer is the catalog of span. Here are 5 values: +1. UNKNOWN (default) +1. DB +1. RPC_FRAMEWORK, for a RPC framework, not an ordinary HTTP +1. HTTP +1. MQ + +Component IDs are defined and protected by SkyWalking project, 0 -> 10000 IDs are reserved. If you want to contribute +a new plugin, you can ask for an official ID, after your pull request approved and automatic test cases accepted by PMC. +Please use > 10000 ID, if you are going to develop a private plugin or don't intend to contribute the plugin to community, +to avoid the ID conflict. + +## Develop a plugin +### Abstract +The basic method to trace is intercepting a Java method, by using byte code manipulation tech and AOP concept. +SkyWalking boxed the byte code manipulation tech and tracing context propagation, +so you just need to define the intercept point(a.k.a. aspect pointcut in Spring) + +### Intercept +SkyWalking provide two common defines to intercept Contructor, instance method and class method. +* Extend `ClassInstanceMethodsEnhancePluginDefine` defines `Contructor` intercept points and `instance method` intercept points. +* Extend `ClassStaticMethodsEnhancePluginDefine` definec `class method` intercept points. + +Of course, you can extend `ClassEnhancePluginDefine` to set all intercept points. But it is unusual. + +### Implement plugin +I will demonstrate about how to implement a plugin by extending `ClassInstanceMethodsEnhancePluginDefine` + +1. Define the target class name +```java +protected abstract ClassMatch enhanceClass(); +``` + +ClassMatch represents how to match the target classes, there are 4 ways: +* byName, through the full class name(package name + `.` + class name) +* byClassAnnotationMatch, through the class existed certain annotations. +* byMethodAnnotationMatch, through the class's method existed certain annotations. +* byHierarchyMatch, throught the class's parent classes or interfaces + +**Attentions**: +* Forbid to use `*.class.getName()` to get the class String name. Recommend you to use literal String. This is for +avoiding ClassLoader issues. +* `by*AnnotationMatch` doesn't support the inherited annotations. +* Don't recommend use `byHierarchyMatch`, unless it is really necessary. Because using it may trigger intercepting +many unexcepted methods, which causes performance issues and concerns. + +Example: +```java +@Override +protected ClassMatch enhanceClassName() { + return byName("org.apache.catalina.core.StandardEngineValve"); +} + +``` + +2. Define an instance method intercept point +```java +protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints(); + +public interface InstanceMethodsInterceptPoint { + /** + * class instance methods matcher. + * + * @return methods matcher + */ + ElementMatcher getMethodsMatcher(); + + /** + * @return represents a class name, the class instance must instanceof InstanceMethodsAroundInterceptor. + */ + String getMethodsInterceptor(); + + boolean isOverrideArgs(); +} +``` +Also use `Matcher` to set the target methods. Return **true** in `isOverrideArgs`, if you want to change the argument +ref in interceptor. + +The following sections will tell you how to implement the interceptor. + +3. Add plugin define into skywalking-plugin.def file +```properties +tomcat-7.x/8.x=TomcatInstrumentation +``` + + +### Implement an interceptor +As an interceptor for an instance method, the interceptor implements +`org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor` +```java +/** + * A interceptor, which intercept method's invocation. The target methods will be defined in {@link + * ClassEnhancePluginDefine}'s subclass, most likely in {@link ClassInstanceMethodsEnhancePluginDefine} + * + * @author wusheng + */ +public interface InstanceMethodsAroundInterceptor { + /** + * called before target method invocation. + * + * @param result change this result, if you want to truncate the method. + * @throws Throwable + */ + void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable; + + /** + * called after target method invocation. Even method's invocation triggers an exception. + * + * @param ret the method's original return value. + * @return the method's actual return value. + * @throws Throwable + */ + Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable; + + /** + * called when occur exception. + * + * @param t the exception occur. + */ + void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Throwable t); +} +``` +Use the core APIs in before, after and exception handle stages. + +### Contribute plugins into Apache SkyWalking repository +We are welcome everyone to contribute plugins. + +Please follow there steps: +1. Submit an issue about which plugins are you going to contribute, including supported version. +1. Create sub modules under `apm-sniffer/apm-sdk-plugin`, and the name should include supported library name and versions +1. Follow this guide to develop. Make sure comments and test cases are provided. +1. Develop and test. +1. Send the pull request and ask for review, and provide the automatic test cases by following PMC members guides. +1. The plugin committers approves your plugins after automatic test cases provided and the tests passed in our CI. +1. The plugin accepted by SkyWalking. diff --git a/docs/en/Skywalking-3-Cross-Process-Propagation-Headers-Protocol.md b/docs/en/Skywalking-Cross-Process-Propagation-Headers-Protocol-v1.md similarity index 84% rename from docs/en/Skywalking-3-Cross-Process-Propagation-Headers-Protocol.md rename to docs/en/Skywalking-Cross-Process-Propagation-Headers-Protocol-v1.md index 40e9b6291725b962364b2f058d6c14f6f3cb86a2..6388f8994c416e52deb068d132e782f5409633a9 100644 --- a/docs/en/Skywalking-3-Cross-Process-Propagation-Headers-Protocol.md +++ b/docs/en/Skywalking-Cross-Process-Propagation-Headers-Protocol-v1.md @@ -1,12 +1,16 @@ -# Skywalking 3 Cross Process Propagation Headers Protocol +# Skywalking Cross Process Propagation Headers Protocol * Version 1.0 -This is the first open edition about `Skywalking 3 Cross Process Propagation Headers Protocol`. The skywalking is more likely an APM system, rather than normal distributed tracing system. The Headers is much more complex than them in order to improving analysis performance of collector. You can find many similar mechanism in other commercial APM system.(Some even much more complex than us) +SkyWalking is more likely an APM system, rather than common distributed tracing system. +The Headers is much more complex than them in order to improving analysis performance of collector. +You can find many similar mechanism in other commercial APM system.(Some even much more complex than us) # Header Item * Header Name: `sw3` * Header Value: Split by `|`, the parts are following. +_The header protocol came from SkyWalking 3, back to 2017. So sw3 header name keeps now._ + ## Values * Trace Segment Id diff --git a/pom.xml b/pom.xml index 8f8d3a094ba1acfc4d8c84e4ed167d6d5473b65a..0473ff50443650affd72fc02fa8d814947ca80a5 100644 --- a/pom.xml +++ b/pom.xml @@ -55,8 +55,8 @@ apm-commons apm-sniffer apm-application-toolkit - apm-network apm-collector + apm-protocol pom diff --git a/travis/push_image.sh b/travis/push_image.sh deleted file mode 100644 index 8c284cce9f337900d9e5df7b8076dc090fb93034..0000000000000000000000000000000000000000 --- a/travis/push_image.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -check_pull_is_tagged() { - if [ "${TRAVIS_TAG}" == "" ]; then - return 1 - else - echo "This build was started by the tag ${TRAVIS_TAG}, push image" - return 0 - fi -} - -check_release_tag() { - tag="${TRAVIS_TAG}" - if [[ "$tag" =~ ^v[0-9.]*-[0-9]{4}$ ]]; then - return 0; - else - echo "The provided tag ${tag} doesn't match that." - return 1; - fi -} - -push_image() { - IMAGE_VERSION=`echo ${TRAVIS_TAG:1}` - docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" - mvn clean package docker:build - docker push skywalking/skywalking-collector:latest - docker push skywalking/skywalking-collector:${IMAGE_VERSION} -} - - -if check_pull_is_tagged && check_release_tag; then - push_image - echo "Push is Done!" -fi \ No newline at end of file