diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index 79a3bb232bdccbb159701bd6e24159dd97eeb224..8b9aea856130b59d4b261a7d7be4f486aa4ae177 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -1,16 +1,24 @@ Please answer these questions before submitting your issue. -### What version of sky-walking are you using? +- Why do you submit this issue? +- [ ] Question or discussion +- [ ] Bug +- [ ] Requirement +- [ ] Feature or performance improvement +___ +### Question +- What do you want to know? -### What version of your OS? +___ +### Bug +- Which version of SkyWalking, OS and JRE? +- Which company or project? -### What version of your JRE? - - -### What company or project? - - -### What did you do? +- What happen? If possible, provide a way for reproducing the error. e.g. demo application, component version. + +___ +### Requirement or improvement +- Please describe about your requirements or improvement suggestions. \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000000000000000000000000000000000000..33068d40daf00e301f1df713252fbe8ddc679d0f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,18 @@ +Please answer these questions before submitting pull request + +- Why submit this pull request? +- [ ] Bug fix +- [ ] New feature provided +- [ ] Improve performance + +- Related issues + +___ +### Bug fix +- Bug description. + +- How to fix? + +___ +### New feature or improvement +- Describe the details and related test reports. diff --git a/README.md b/README.md index 0ac610447c974f14641e474f16f8b566410b8e15..5ba47c4d7cce05d58db77c23bc3817d8afeb3d38 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,10 @@ Apache SkyWalking | [中文](README_ZH.md) microservices, cloud native and container-based (Docker, K8s, Mesos) architectures. Underlying technology is a distributed tracing system. +[![GitHub stars](https://img.shields.io/github/stars/apache/incubator-skywalking.svg?style=for-the-badge&label=Stars&logo=github)](https://github.com/apache/incubator-skywalking) +[![Twitter Follow](https://img.shields.io/twitter/follow/asfskywalking.svg?style=for-the-badge&label=Follow&logo=twitter)](https://twitter.com/AsfSkyWalking) + [![Build Status](https://travis-ci.org/apache/incubator-skywalking.svg?branch=master)](https://travis-ci.org/apache/incubator-skywalking) -[![Twitter URL](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/AsfSkyWalking) [![Join the chat at https://gitter.im/sky-walking/Lobby](https://badges.gitter.im/openskywalking/Lobby.svg)](https://gitter.im/openskywalking/Lobby) [![OpenTracing-1.x Badge](https://img.shields.io/badge/OpenTracing--1.x-enabled-blue.svg)](http://opentracing.io) diff --git a/README_ZH.md b/README_ZH.md index 6a274fc04f9b6679e8a3895d6ab49108f99e1add..06dd40de72e60f83db1c539740f0a2b7d2a79e3a 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -6,8 +6,10 @@ Apache SkyWalking | [English](README.md) **SkyWalking**: 针对分布式系统的APM(应用性能监控)系统,特别针对微服务、cloud native和容器化(Docker, K8s, Mesos)架构, 其核心是个分布式追踪系统。 +[![GitHub stars](https://img.shields.io/github/stars/apache/incubator-skywalking.svg?style=for-the-badge&label=Stars&logo=github)](https://github.com/apache/incubator-skywalking) +[![Twitter Follow](https://img.shields.io/twitter/follow/asfskywalking.svg?style=for-the-badge&label=Follow&logo=twitter)](https://twitter.com/AsfSkyWalking) + [![Build Status](https://travis-ci.org/apache/incubator-skywalking.svg?branch=master)](https://travis-ci.org/apache/incubator-skywalking) -[![Twitter URL](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/AsfSkyWalking) [![Join the chat at https://gitter.im/openskywalking/Lobby](https://badges.gitter.im/openskywalking/Lobby.svg)](https://gitter.im/openskywalking/Lobby) [![OpenTracing-1.x Badge](https://img.shields.io/badge/OpenTracing--1.x-enabled-blue.svg)](http://opentracing.io) diff --git a/apm-collector/apm-collector-analysis/analysis-metric/metric-provider/src/main/java/org/apache/skywalking/apm/collector/analysis/metric/provider/worker/segment/SegmentCostSpanListener.java b/apm-collector/apm-collector-analysis/analysis-metric/metric-provider/src/main/java/org/apache/skywalking/apm/collector/analysis/metric/provider/worker/segment/SegmentCostSpanListener.java index 9c16671e88bc010daa532ea84127655ebd7ecc7b..d12cfca970319c37fa8d660523f9d6a9cf54ad26 100644 --- a/apm-collector/apm-collector-analysis/analysis-metric/metric-provider/src/main/java/org/apache/skywalking/apm/collector/analysis/metric/provider/worker/segment/SegmentCostSpanListener.java +++ b/apm-collector/apm-collector-analysis/analysis-metric/metric-provider/src/main/java/org/apache/skywalking/apm/collector/analysis/metric/provider/worker/segment/SegmentCostSpanListener.java @@ -33,6 +33,7 @@ import org.apache.skywalking.apm.collector.cache.service.ServiceNameCacheService import org.apache.skywalking.apm.collector.core.graph.Graph; import org.apache.skywalking.apm.collector.core.graph.GraphManager; import org.apache.skywalking.apm.collector.core.module.ModuleManager; +import org.apache.skywalking.apm.collector.core.util.BooleanUtils; import org.apache.skywalking.apm.collector.core.util.TimeBucketUtils; import org.apache.skywalking.apm.collector.storage.table.segment.SegmentCost; import org.slf4j.Logger; @@ -98,7 +99,7 @@ public class SegmentCostSpanListener implements EntrySpanListener, ExitSpanListe Graph graph = GraphManager.INSTANCE.findGraph(MetricGraphIdDefine.SEGMENT_COST_GRAPH_ID, SegmentCost.class); logger.debug("segment cost listener build"); for (SegmentCost segmentCost : segmentCosts) { - segmentCost.setIsError(isError); + segmentCost.setIsError(BooleanUtils.booleanToValue(isError)); segmentCost.setTimeBucket(timeBucket); graph.start(segmentCost); } diff --git a/apm-collector/apm-collector-analysis/analysis-register/register-provider/src/main/java/org/apache/skywalking/apm/collector/analysis/register/provider/register/IdAutoIncrement.java b/apm-collector/apm-collector-analysis/analysis-register/register-provider/src/main/java/org/apache/skywalking/apm/collector/analysis/register/provider/register/IdAutoIncrement.java index 896e0efeb9c2b221525ccc0ce7593389666e71de..cf1827e883bf9e18eb43e7dca5d05dea290ed901 100644 --- a/apm-collector/apm-collector-analysis/analysis-register/register-provider/src/main/java/org/apache/skywalking/apm/collector/analysis/register/provider/register/IdAutoIncrement.java +++ b/apm-collector/apm-collector-analysis/analysis-register/register-provider/src/main/java/org/apache/skywalking/apm/collector/analysis/register/provider/register/IdAutoIncrement.java @@ -25,18 +25,20 @@ public enum IdAutoIncrement { INSTANCE; public int increment(int min, int max) { - int instanceId; + int id; if (min == max) { - instanceId = -1; + if (min == 0) { + id = -1; + } else { + id = 1; + } } else if (min + max == 0) { - instanceId = max + 1; + id = max + 1; } else if (min + max > 0) { - instanceId = min - 1; - } else if (max < 0) { - instanceId = 1; + id = min - 1; } else { - instanceId = max + 1; + id = max + 1; } - return instanceId; + return id; } } diff --git a/apm-collector/apm-collector-analysis/analysis-register/register-provider/src/test/java/org/apache/skywalking/apm/collector/analysis/register/provider/register/IdAutoIncrementTestCase.java b/apm-collector/apm-collector-analysis/analysis-register/register-provider/src/test/java/org/apache/skywalking/apm/collector/analysis/register/provider/register/IdAutoIncrementTestCase.java new file mode 100644 index 0000000000000000000000000000000000000000..ad9d0e28588b20b5c2e3a32ec7c036c7d7950283 --- /dev/null +++ b/apm-collector/apm-collector-analysis/analysis-register/register-provider/src/test/java/org/apache/skywalking/apm/collector/analysis/register/provider/register/IdAutoIncrementTestCase.java @@ -0,0 +1,46 @@ +/* + * 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.collector.analysis.register.provider.register; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author peng-yongsheng + */ +public class IdAutoIncrementTestCase { + + @Test + public void testIncrement() { + int id = IdAutoIncrement.INSTANCE.increment(0, 0); + Assert.assertEquals(-1, id); + + id = IdAutoIncrement.INSTANCE.increment(-1, -1); + Assert.assertEquals(1, id); + + id = IdAutoIncrement.INSTANCE.increment(-1, 1); + Assert.assertEquals(2, id); + + id = IdAutoIncrement.INSTANCE.increment(-1, 2); + Assert.assertEquals(-2, id); + + id = IdAutoIncrement.INSTANCE.increment(-2, 2); + Assert.assertEquals(3, id); + } +} diff --git a/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/table/segment/SegmentCost.java b/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/table/segment/SegmentCost.java index cac209d8c3a0696e50a44176f4d51bb59f80cc81..475019bd028d14e843d9128d578c26f24d297d09 100644 --- a/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/table/segment/SegmentCost.java +++ b/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/table/segment/SegmentCost.java @@ -22,7 +22,6 @@ import org.apache.skywalking.apm.collector.core.data.Column; import org.apache.skywalking.apm.collector.core.data.StreamData; import org.apache.skywalking.apm.collector.core.data.operator.CoverOperation; import org.apache.skywalking.apm.collector.core.data.operator.NonOperation; -import org.apache.skywalking.apm.collector.core.util.BooleanUtils; /** * @author peng-yongsheng @@ -127,11 +126,11 @@ public class SegmentCost extends StreamData { setDataInteger(0, applicationId); } - public Boolean getIsError() { - return BooleanUtils.valueToBoolean(getDataInteger(1)); + public Integer getIsError() { + return getDataInteger(1); } - public void setIsError(Boolean isError) { - setDataInteger(0, BooleanUtils.booleanToValue(isError)); + public void setIsError(Integer isError) { + setDataInteger(1, isError); } } diff --git a/apm-protocol/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 index a0ab7bd97d35f122bbd2056aac56dd2abb5be1b7..b23f30cf3b470a3953d7715d4cc3813f19c43816 100644 --- a/apm-protocol/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 @@ -76,6 +76,7 @@ public class ComponentsDefine { public static final OfficialComponent ROCKET_MQ = new OfficialComponent(25, "RocketMQ"); + public static final OfficialComponent HTTP_ASYNC_CLIENT = new OfficialComponent(26, "httpasyncclient"); private static ComponentsDefine INSTANCE = new ComponentsDefine(); @@ -86,7 +87,7 @@ public class ComponentsDefine { } public ComponentsDefine() { - components = new String[26]; + components = new String[27]; addComponent(TOMCAT); addComponent(HTTPCLIENT); addComponent(DUBBO); @@ -112,6 +113,7 @@ public class ComponentsDefine { addComponent(GRPC); addComponent(ELASTIC_JOB); addComponent(ROCKET_MQ); + addComponent(HTTP_ASYNC_CLIENT); } private void addComponent(OfficialComponent component) { 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 index b63946d8b2d67fcbcde133a942da7971145af90c..b60d0a12626df2caafad7412ff61d78133058ef5 100644 --- 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 @@ -1,7 +1,17 @@ +type Alarm { + items: [AlarmItem!]! + count: Int! +} + type AlarmItem { + # Typical include: Application Code + cause type. This is a short description. + title: String! + # Include all related info to trigger this alarm. + # such as: threshold, trigger value, relation(greater or lower), last time content: String! startTime: String! alertType: AlarmType! + causeType: CauseType! } enum AlarmType { @@ -10,6 +20,11 @@ enum AlarmType { SERVICE } +enum CauseType { + LOW_SUCCESS_RATE, + SLOW_RESPONSE +} + extend type Query { - loadAlertList(keyword: String, alertType: AlarmType, duration:Duration!):[AlarmItem] + loadAlertList(keyword: String, alertType: AlarmType, duration:Duration!, paging: Pagination!): Alarm } \ 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 index f8ccf0eb9f73397931edb0326dc8690bf815fda0..91d0b2d795e125eb8547775e0c6b8dbc0a835ae0 100644 --- 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 @@ -8,20 +8,22 @@ type ApplicationNode implements Node { # 2 Digits after floating point. sla: Float! # The number of incoming calls - calls: Long! + callsPerSec: Long! + # Unit: millisecond + responseTimePerSec: Int! # ref: http://www.apdex.org/ # Max value is 1 # 2 Digits after floating point. apdex: Float! + # Whether the application alerts? + # Default value is false. + isAlarm: Boolean! # The number of servers in the application code numOfServer: Int! # The number of servers alerting numOfServerAlarm: Int! # The number of services alerting numOfServiceAlarm: Int! - # Incoming request node, means User or outside system access the cluster from this. - # Recommend the UI generate a User node for each incoming node - isIncomingNode: Boolean } # The conjectural node generated by exit span @@ -33,8 +35,8 @@ type ConjecturalNode implements Node { extend type Query { - getAllApplication(duration: Duration!): [ApplicationNode] + getAllApplication(duration: Duration!): [ApplicationNode!]! getApplicationTopology(applicationId: ID!, duration: Duration!): Topology - getSlowService(applicationId: ID!, duration: Duration!): [ServiceInfo!] - getServerThroughput(applicationId: ID!, duration: Duration!): [AppServerInfo!] + getSlowService(applicationId: ID!, duration: Duration!, top: Int!): [ServiceInfo!]! + getServerThroughput(applicationId: ID!, duration: Duration!, top: Int!): [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 index 853f362582a8b5bfb16a1b4576c970be805058e3..04f21eeb32586cb932da44804a5b0a253675b24b 100644 --- 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 @@ -1,5 +1,6 @@ schema { query: Query + mutation: Mutation } #Root node @@ -7,6 +8,10 @@ type Query { version: String } +type Mutation { + 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. @@ -39,6 +44,14 @@ enum Step { SECOND } +input Pagination { + # pageNum starts in 1, the default is 1. + pageNum: Int + pageSize: Int! + # default false + needTotal: Boolean +} + ###################################### # Common Metrics and Trends ###################################### @@ -47,17 +60,17 @@ type ResponseTimeTrend { } type ThroughputTrend { - trendList: [Int!] + trendList: [Int!]! } type SLATrend { - trendList: [Int!] + trendList: [Int!]! } # The overview topology of the whole application cluster or services, type Topology { - nodes: [Node]! - calls: [Call] + nodes: [Node!]! + calls: [Call!]! } # The base Node of all node types in topology @@ -74,6 +87,15 @@ interface Node { type: String } +# Incoming request node, means User or outside system access the cluster from this. +type VisualUserNode implements Node { + id: ID! + # Constant, value = "User" + name: String! + # Constant, value = "USER" + type: String +} + # The Call represents a directed distributed call, # from the `source` to the `target`. type Call { diff --git a/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/config.graphqls b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/config.graphqls new file mode 100644 index 0000000000000000000000000000000000000000..aaa102e1c95175cc2535c2f683d00a2a8bb1c679 --- /dev/null +++ b/apm-protocol/apm-ui-protocol/src/main/resources/ui-graphql/config.graphqls @@ -0,0 +1,38 @@ +input TTLConfigItem { + unit: Step! + value: Int! +} + +type ExistedTTLConfigs{ + ttl: [TTL!]! +} + +type TTL { + unit: Step! + value: Int! +} + +input AlarmThreshold { + type: AlarmType! + threshold: Int! + causeType: CauseType! +} + +type ExistedAlarmThresholds { + items: [ExistedAlarmThresholdItem!]! +} + +type ExistedAlarmThresholdItem { + threshold: Int! + causeType: CauseType! +} + +extend type Mutation { + setDataTTLConfigs(ttl: [TTLConfigItem!]!): Boolean! + setAlarmThreshold(thresholds: [AlarmThreshold!]!): Boolean! +} + +extend type Query { + queryAllDataTTLConfigs: ExistedTTLConfigs! + queryAlarmThresholds(alarmType: AlarmType): ExistedAlarmThresholds! +} \ No newline at end of file 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 index e7b0bc2d65b1e3df0e162602169ca17642c013c1..04b1033a618c918058df4c3b20741625c763c3bf 100644 --- 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 @@ -15,7 +15,7 @@ type AlarmTrend { # Query all conjectural applications based on the given duration # All applications here are not installed agent. type ConjecturalAppBrief { - apps: [ConjecturalApp!] + apps: [ConjecturalApp!]! } # The basic info of the conjectural application, @@ -32,6 +32,6 @@ extend type Query { getClusterBrief(duration: Duration!): ClusterBrief getAlarmTrend(duration: Duration!): AlarmTrend getConjecturalApps(duration: Duration!): ConjecturalAppBrief - getTopNSlowService(duration: Duration!, topN: Int!): [ServiceInfo!] - getTopNServerThroughput(duration: Duration!, topN: Int!): [AppServerInfo!] + 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 index eac33a7dcf3f596b0702251db8cc8cfea8be0500..ddd41c680ba10aa98236282c48f346a04430365b 100644 --- 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 @@ -10,30 +10,31 @@ type AppServerInfo { os: String host: String pid: Int - IPv4: String - IPv6: String + ipv4: String + ipv6: String } type CPUTrend { - cost: [Int!] + cost: [Int!]! } # The gc trend represents the numbers of Garbage Collector execution type GCTrend { - youngGC: [Int!] - oldGC: [Int!] + 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!] + heap: [Int!]! + maxHeap: [Int!]! + noheap: [Int!]! + maxNoheap: [Int!]! } extend type Query { - searchServer(keyword: String!, duration: Duration!): [AppServerInfo] + searchServer(keyword: String!, duration: Duration!): [AppServerInfo!]! + getAllServer(applicationId: ID!, duration: Duration!): [AppServerInfo!]! getServerResponseTimeTrend(serverId: ID!, duration: Duration!): ResponseTimeTrend getServerTPSTrend(serverId: ID!, duration: Duration!): ThroughputTrend getCPUTrend(serverId: ID!, duration: Duration!): CPUTrend 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 index 3e33c8f9e4f4f58f8dc39eb9a6a4b4a2c4a98d83..a5b44557a9f54a7be4fd6323b1da7c18bb094a5a 100644 --- 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 @@ -27,7 +27,7 @@ type TraceItem { } extend type Query { - searchService(keyword: String!, duration: Duration!): [ServiceNode] + searchService(keyword: String!, duration: Duration!, topN: Int!): [ServiceNode!]! getServiceResponseTimeTrend(serviceId: ID!, duration: Duration!): ResponseTimeTrend getServiceTPSTrend(serviceId: ID!, duration: Duration!): ThroughputTrend getServiceSLATrend(serviceId: ID!, duration: Duration!): SLATrend 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 index 4e2e1a0ec5ad9672080269faa0bb10ad43d1fe9a..d5e2de8f3639e1796dc2bd1f0e98a0a116289326 100644 --- 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 @@ -1,6 +1,7 @@ # The list of traces type TraceBrief { - traces: [BasicTrace!] + traces: [BasicTrace!]! + total: Int! } # Trace basic info @@ -23,8 +24,7 @@ input TraceQueryCondition { minTraceDuration: Int # The max time of trace maxTraceDuration: Int - topN: Boolean - needTotal: Int + paging: Pagination! } enum QueryOrder { @@ -34,21 +34,15 @@ enum QueryOrder { # 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!] + traceId: ID! + segmentId: ID! spanId: Int! parentSpanId: Int! + refs: [Ref!]! startTime: Long! endTime: Long! operationName: String @@ -60,17 +54,25 @@ type Span { isError: Boolean # There are 5 layers: Unknown, Database, RPCFramework, Http, MQ and Cache layer: String - tags: [KeyValue!] - logs: [LogEntity!] + tags: [KeyValue!]! + logs: [LogEntity!]! } # Ref represents the link between the segment and its parents. +# The parent(ref) may not exists, which means batch process. +# The UI should display a list, representing the other trace IDs. type Ref { + traceId: ID! parentSegmentId: ID! parentSpanId: Int! # Ref type represents why did the ref happen. # Include: 1) CrossProcess 2) CrossThread - type: String! + type: RefType! +} + +enum RefType { + CROSS_PROCESS, + CROSS_THREAD } type KeyValue { @@ -86,4 +88,4 @@ type LogEntity { 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 index f017d6844147d105c1110eaf055b89edca2aff38..5c93a8e93d0b99a1310a29878c4b9309529026bf 100644 --- 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 @@ -43,6 +43,7 @@ public class GraphQLScriptTest { typeRegistry.merge(schemaParser.parse(loadSchema("server-layer.graphqls"))); typeRegistry.merge(schemaParser.parse(loadSchema("service-layer.graphqls"))); typeRegistry.merge(schemaParser.parse(loadSchema("alarm.graphqls"))); + typeRegistry.merge(schemaParser.parse(loadSchema("config.graphqls"))); RuntimeWiring wiring = buildRuntimeWiring(); assertTrue(schemaGenerator.makeExecutableSchema(typeRegistry, wiring).getAllTypesAsList().size() > 0); } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java index 54f660ed01ad87067aa95d75d9474bd6cab4e57a..e8802d472446e0f81495a05195ae670dd12893dd 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java @@ -59,6 +59,16 @@ public final class Tags { */ public static final StringTag DB_BIND_VARIABLES = new StringTag("db.bind_vars"); + /** + * MQ_BROKER records the broker address of message-middleware + */ + public static final StringTag MQ_BROKER = new StringTag("mq.broker"); + + /** + * MQ_TOPIC records the topic name of message-middleware + */ + public static final StringTag MQ_TOPIC = new StringTag("mq.topic"); + public static final class HTTP { public static final StringTag METHOD = new StringTag("http.method"); } diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..3c4baf902a4149e35e6b5588abef7c687d0c008b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml @@ -0,0 +1,71 @@ + + + + + 4.0.0 + + org.apache.skywalking + apm-sdk-plugin + 5.0.0-alpha + + + apm-httpasyncclient-4.x-plugin + + httpasyncclient-4.x-plugin + http://maven.apache.org + + + UTF-8 + + + + + org.apache.httpcomponents + httpasyncclient + 4.1.1 + provided + + + org.apache.httpcomponents + httpasyncclient-cache + 4.1.1 + provided + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + + attach-sources + + jar + + + + + + + diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/ConnectIterceptor.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/ConnectIterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..09725ebf35398e154f27118440b155d83498c337 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/ConnectIterceptor.java @@ -0,0 +1,62 @@ +/* + * 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.httpasyncclient.v4; + +import java.lang.reflect.Method; +import java.net.InetSocketAddress; +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.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; + +/** + * Pass ref accross thread by SessionRequest. + * + * @author liyuntao + */ + +public class ConnectIterceptor implements InstanceMethodsAroundInterceptor { + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + + } + + @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + ((EnhancedInstance)ret).setSkyWalkingDynamicField(ContextManager.capture()); + + InetSocketAddress remoteAddress = (InetSocketAddress)allArguments[0]; + String peer = remoteAddress.toString().substring(1); + + Object[] cacheValue = new Object[3]; + cacheValue[0] = ContextManager.capture(); + cacheValue[1] = peer; + objInst.setSkyWalkingDynamicField(cacheValue); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(t); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/DefaultConnectingIOReactorIterceptor.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/DefaultConnectingIOReactorIterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..bb7c44f3febd3922525b3517e55102db1a807c31 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/DefaultConnectingIOReactorIterceptor.java @@ -0,0 +1,61 @@ +/* + * 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.httpasyncclient.v4; + +import java.lang.reflect.Method; +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.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; + +/** + * Create local span :httpasyncclient/SocketChannel, to showcase the ability to connect to the remote host. + * + * @author liyuntao + */ + +public class DefaultConnectingIOReactorIterceptor implements InstanceMethodsAroundInterceptor { + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + Object[] cacheValue = (Object[])objInst.getSkyWalkingDynamicField(); + final ContextCarrier contextCarrier = new ContextCarrier(); + AbstractSpan span = ContextManager.createExitSpan("httpasyncclient/" + method.getName(), contextCarrier, cacheValue[1].toString()); + ContextManager.continued((ContextSnapshot)cacheValue[0]); + span.setComponent(ComponentsDefine.HTTP_ASYNC_CLIENT).setLayer(SpanLayer.HTTP); + } + + @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) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(t); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncResponseConsumerInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncResponseConsumerInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..2446652668ea6d9d746d44f39e1631dd49f973af --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncResponseConsumerInterceptor.java @@ -0,0 +1,66 @@ +/* + * 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.httpasyncclient.v4; + +import java.lang.reflect.Method; +import org.apache.http.nio.protocol.HttpAsyncRequestProducer; +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; + +/** + * End a local span for {@link org.apache.http.impl.nio.client.CloseableHttpAsyncClient#execute} called by + * application. + * + * @author liyuntao + */ + +public class HttpAsyncResponseConsumerInterceptor implements InstanceMethodsAroundInterceptor { + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + + HttpAsyncRequestProducer producer = (HttpAsyncRequestProducer)allArguments[0]; + String uri = producer.generateRequest().getRequestLine().getUri(); + String requestMethod = producer.generateRequest().getRequestLine().getMethod(); + AbstractSpan span = ContextManager.createLocalSpan("httpasyncclient/" + method.getName()); + Tags.HTTP.METHOD.set(span, requestMethod); + span.setComponent(ComponentsDefine.HTTP_ASYNC_CLIENT).setLayer(SpanLayer.HTTP); + Tags.URL.set(span, uri); + + } + + @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) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(t); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpHostInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpHostInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..02c096eda491c04b173bdf313f4c8bfc78a8b93f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpHostInterceptor.java @@ -0,0 +1,66 @@ +/* + * 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.httpasyncclient.v4; + +import java.lang.reflect.Method; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +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; + +/** + * End a local span for {@link org.apache.http.impl.nio.client.CloseableHttpAsyncClient#execute} called by + * application. + * + * @author liyuntao + */ + +public class HttpHostInterceptor implements InstanceMethodsAroundInterceptor { + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + + HttpHost producer = (HttpHost)allArguments[0]; + String uri = producer.toURI(); + AbstractSpan span = ContextManager.createLocalSpan("httpasyncclient/" + method.getName()); + span.setComponent(ComponentsDefine.HTTP_ASYNC_CLIENT).setLayer(SpanLayer.HTTP); + Tags.HTTP.METHOD.set(span, ((HttpRequest)allArguments[1]).getRequestLine().getMethod()); + Tags.URL.set(span, uri); + + } + + @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) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(t); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/ProcessResponseInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/ProcessResponseInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..1cfc1db3a05f7794a0d35fc183ddeff567c8b99a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/ProcessResponseInterceptor.java @@ -0,0 +1,66 @@ +/* + * 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.httpasyncclient.v4; + +import java.lang.reflect.Method; +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; + +/** + * 1.End exit span. + * 2.Create a local span of callback. + * 3.End local span:AsyncThread/execute. + * + * @author liyuntao + */ + +public class ProcessResponseInterceptor implements InstanceMethodsAroundInterceptor { + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + AbstractSpan activeSpan = ContextManager.activeSpan(); + String uri = activeSpan.getOperationName(); + //stop exitSpan + ContextManager.stopSpan(); + AbstractSpan localSpan = ContextManager.createLocalSpan("callback:" + uri); + localSpan.setComponent(ComponentsDefine.HTTP_ASYNC_CLIENT).setLayer(SpanLayer.HTTP); + } + + @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + //stop local span:callback + ContextManager.stopSpan(); + //stop local span:AsyncThread/execute + ContextManager.stopSpan(); + + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(t); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/SessionRequestImplIterceptor.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/SessionRequestImplIterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..e5e339565e87f8fb06eb38882099dfa6dfbe37ae --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/SessionRequestImplIterceptor.java @@ -0,0 +1,54 @@ +/* + * 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.httpasyncclient.v4; + +import java.lang.reflect.Method; +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.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; + +/** + * Set local span false When connect to the remote host failed . + * + * @author liyuntao + */ + +public class SessionRequestImplIterceptor implements InstanceMethodsAroundInterceptor { + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + + } + + @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(t); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/SetResponseInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/SetResponseInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..65fd2b726ca3e6726d5bca42a3863d82bfab17ed --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/SetResponseInterceptor.java @@ -0,0 +1,63 @@ +/* + * 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.httpasyncclient.v4; + +import java.lang.reflect.Method; +import org.apache.http.HttpResponse; +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.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; + +/** + * End exit span and create a local span of future/Callback. + * + * @author liyuntao + */ + +public class SetResponseInterceptor implements InstanceMethodsAroundInterceptor { + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + if (null == allArguments[0]) { + return; + } + AbstractSpan span = ContextManager.activeSpan(); + int statusCode = ((HttpResponse)allArguments[0]).getStatusLine().getStatusCode(); + if (statusCode >= 400) { + span.errorOccurred(); + Tags.STATUS_CODE.set(span, Integer.toString(statusCode)); + } + + } + + @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(t); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/StateInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/StateInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..156b1ca07c148b27d6e75fd65ad2fc4406d58b5b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/StateInterceptor.java @@ -0,0 +1,84 @@ +/* + * 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.httpasyncclient.v4; + +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import org.apache.http.client.methods.HttpRequestWrapper; +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; + +/** + * Create exit span of httpasyncclient. + * + * @author liyuntao + */ + +public class StateInterceptor implements InstanceMethodsAroundInterceptor { + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + if (null == allArguments[0]) { + return; + } + HttpRequestWrapper httpRequest = (HttpRequestWrapper)allArguments[0]; + String uri = httpRequest.getOriginal().getRequestLine().getUri(); + AbstractSpan span = null; + final ContextCarrier contextCarrier = new ContextCarrier(); + try { + URL url = new URL(httpRequest.getOriginal().getRequestLine().getUri()); + String remotePeer = url.getHost() + ":" + url.getPort(); + span = ContextManager.createExitSpan(url.getPath(), contextCarrier, remotePeer); + } catch (MalformedURLException e) { + throw e; + } + span.setComponent(ComponentsDefine.HTTP_ASYNC_CLIENT); + Tags.URL.set(span, uri); + Tags.HTTP.METHOD.set(span, httpRequest.getOriginal().getRequestLine().getMethod()); + SpanLayer.asHttp(span); + + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + httpRequest.setHeader(next.getHeadKey(), next.getHeadValue()); + } + + } + + @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(t); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/SuccessInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/SuccessInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..c9f0551661fe524b4866e9327962deef77e4a5fa --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/SuccessInterceptor.java @@ -0,0 +1,61 @@ +/* + * 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.httpasyncclient.v4; + +import java.lang.reflect.Method; +import org.apache.http.nio.reactor.SessionRequest; +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; + +/** + * Create a local sapn and passing ref accross thread by SessionRequest. + * + * @author liyuntao + */ + +public class SuccessInterceptor implements InstanceMethodsAroundInterceptor { + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + SessionRequest request = (SessionRequest)allArguments[0]; + AbstractSpan localSpan = ContextManager.createLocalSpan("AsyncThread/execute"); + localSpan.setComponent(ComponentsDefine.HTTP_ASYNC_CLIENT).setLayer(SpanLayer.HTTP); + Object cacheValue = ((EnhancedInstance)request).getSkyWalkingDynamicField(); + ContextManager.continued((ContextSnapshot)cacheValue); + + } + + @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(t); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/AbstractNIOConnPoolInstrumentation.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/AbstractNIOConnPoolInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..4b26186265a7e71e9431690fda9158683152fc06 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/AbstractNIOConnPoolInstrumentation.java @@ -0,0 +1,76 @@ +/* + * 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.httpasyncclient.v4.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.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link AbstractNIOConnPoolInstrumentation} presents that skywalking intercept {@link + * org.apache.http.nio.protocol.AbstractNIOConnPool #requestCompleted}. + * + * @author liyuntao + */ + +public class AbstractNIOConnPoolInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.apache.http.nio.pool.AbstractNIOConnPool"; + private static final String START_LOCAL_SUCCESS_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.httpasyncclient.v4.SuccessInterceptor"; + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("requestCompleted"); + } + + @Override + public String getMethodsInterceptor() { + return START_LOCAL_SUCCESS_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + + }; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/DefaultConnectingIOReactorInstrumentation.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/DefaultConnectingIOReactorInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..80254acb61c1e146ebcd1bebc454b6db15fff407 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/DefaultConnectingIOReactorInstrumentation.java @@ -0,0 +1,91 @@ +/* + * 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.httpasyncclient.v4.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.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link DefaultConnectingIOReactorInstrumentation} presents that skywalking intercepts {@link + * org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor#processEvent} + * + * @author liyuntao + */ + +public class DefaultConnectingIOReactorInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor"; + private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.httpasyncclient.v4.DefaultConnectingIOReactorIterceptor"; + private static final String LOCAL_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.httpasyncclient.v4.ConnectIterceptor"; + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("processEvent"); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("connect"); + } + + @Override + public String getMethodsInterceptor() { + return LOCAL_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/ExecuteInstrumentation.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/ExecuteInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..d0e7e7d8b66ab0a2e885cb8a6af3e31b7b996209 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/ExecuteInstrumentation.java @@ -0,0 +1,92 @@ +/* + * 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.httpasyncclient.v4.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.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link ExecuteInstrumentation} presents that skywalking intercepts {@link org.apache.http.impl.nio.client.CloseableHttpAsyncClient#execute} + * + * @author liyuntao + */ + +public class ExecuteInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.apache.http.impl.nio.client.CloseableHttpAsyncClient"; + private static final String CONSUMER_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.httpasyncclient.v4.HttpAsyncResponseConsumerInterceptor"; + private static final String HOST_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.httpasyncclient.v4.HttpHostInterceptor"; + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("execute").and(takesArgumentWithType(0, "org.apache.http.nio.protocol.HttpAsyncRequestProducer")).and(takesArguments(3)); + } + + @Override + public String getMethodsInterceptor() { + return CONSUMER_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("execute").and(takesArguments(4)).and(takesArgumentWithType(0, "org.apache.http.HttpHost")); + } + + @Override + public String getMethodsInterceptor() { + return HOST_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/ProcessResponseInstrumentation.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/ProcessResponseInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..fe4291c6721b0068cba4864c3ee1e7293c3dfc30 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/ProcessResponseInstrumentation.java @@ -0,0 +1,74 @@ +/* + * 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.httpasyncclient.v4.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.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link ProcessResponseInstrumentation} presents that skywalking intercept {@link + * org.apache.http.nio.protocol.HttpAsyncRequestExecutor#processResponse,#connected} . + * + * @author liyuntao + */ + +public class ProcessResponseInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.apache.http.nio.protocol.HttpAsyncRequestExecutor"; + private static final String END_EXIT_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.httpasyncclient.v4.ProcessResponseInterceptor"; + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("processResponse"); + } + + @Override + public String getMethodsInterceptor() { + return END_EXIT_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + + }; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/SessionRequestImplInstrumentation.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/SessionRequestImplInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..0fac8ab40e549eca98bdff1bfa2770ba0b3185ca --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/SessionRequestImplInstrumentation.java @@ -0,0 +1,74 @@ +/* + * 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.httpasyncclient.v4.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.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link SessionRequestImplInstrumentation} presents that skywalking intercepts {@link + * org.apache.http.impl.nio.reactor.SessionRequestImpl#failed(final IOException exception)} + * + * @author liyuntao + */ + +public class SessionRequestImplInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.apache.http.impl.nio.reactor.SessionRequestImpl"; + private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.httpasyncclient.v4.SessionRequestImplIterceptor"; + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("failed"); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/StateInstrumentation.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/StateInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..8e5d4f7ef2a9547999b9705113a1bb771c053b13 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/define/StateInstrumentation.java @@ -0,0 +1,92 @@ +/* + * 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.httpasyncclient.v4.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.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link StateInstrumentation} presents that skywalking intercept {@link org.apache.http.nio.protocol.HttpAsyncRequestExecutor$State#setRequest + * #setResponse} . + * + * @author liyuntao + */ + +public class StateInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.apache.http.nio.protocol.HttpAsyncRequestExecutor$State"; + private static final String START_EXIT_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.httpasyncclient.v4.StateInterceptor"; + private static final String END_EXIT_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.httpasyncclient.v4.SetResponseInterceptor"; + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("setRequest"); + } + + @Override + public String getMethodsInterceptor() { + return START_EXIT_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("setResponse"); + } + + @Override + public String getMethodsInterceptor() { + return END_EXIT_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + + }; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000000000000000000000000000000000..13e0ee534e783606581cb0392b2cad43a5dddb1f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,8 @@ +httpasyncclient-4.x=org.apache.skywalking.apm.plugin.httpasyncclient.v4.define.ExecuteInstrumentation +httpasyncclient-4.x=org.apache.skywalking.apm.plugin.httpasyncclient.v4.define.DefaultConnectingIOReactorInstrumentation +httpasyncclient-4.x=org.apache.skywalking.apm.plugin.httpasyncclient.v4.define.SessionRequestImplInstrumentation +httpasyncclient-4.x=org.apache.skywalking.apm.plugin.httpasyncclient.v4.define.AbstractNIOConnPoolInstrumentation +httpasyncclient-4.x=org.apache.skywalking.apm.plugin.httpasyncclient.v4.define.StateInstrumentation +httpasyncclient-4.x=org.apache.skywalking.apm.plugin.httpasyncclient.v4.define.ProcessResponseInstrumentation + + diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/StateInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/StateInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..05a33f211a6282fd5a93cc11e9887b33238df3bd --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/StateInterceptorTest.java @@ -0,0 +1,179 @@ +/* + * 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.httpasyncclient.v4; + +import java.util.List; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.ProtocolVersion; +import org.apache.http.RequestLine; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +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.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.TracingSegmentRunner; +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.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +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.mockito.Matchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +@PrepareForTest(HttpHost.class) +public class StateInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule agentServiceRule = new AgentServiceRule(); + + private StateInterceptor stateInterceptor; + + private SetResponseInterceptor setResponseInterceptor; + + private ProcessResponseInterceptor processResponseInterceptor; + @Mock + private HttpHost httpHost; + @Mock + private HttpRequestWrapper request; + @Mock + private HttpRequest httpRequest; + @Mock + private HttpResponse httpResponse; + @Mock + private StatusLine statusLine; + + private Object[] allArguments; + private Class[] argumentsType; + + @Mock + private EnhancedInstance enhancedInstance; + + @Before + public void setUp() throws Exception { + ServiceManager.INSTANCE.boot(); + stateInterceptor = new StateInterceptor(); + setResponseInterceptor = new SetResponseInterceptor(); + processResponseInterceptor = new ProcessResponseInterceptor(); + + PowerMockito.mock(HttpHost.class); + when(statusLine.getStatusCode()).thenReturn(200); + when(httpResponse.getStatusLine()).thenReturn(statusLine); + when(httpHost.getHostName()).thenReturn("127.0.0.1"); + when(httpHost.getSchemeName()).thenReturn("http"); + when(request.getOriginal()).thenReturn(httpRequest); + when(httpRequest.getRequestLine()).thenReturn(new RequestLine() { + @Override + public String getMethod() { + return "GET"; + } + + @Override + public ProtocolVersion getProtocolVersion() { + return new ProtocolVersion("http", 1, 1); + } + + @Override + public String getUri() { + return "http://127.0.0.1:8080/test-web/httpasync"; + } + }); + when(httpHost.getPort()).thenReturn(8080); + + allArguments = new Object[] {request}; + argumentsType = new Class[] {request.getClass()}; + } + + @Test + public void testHttpClient() throws Throwable { + AbstractSpan span = ContextManager.createLocalSpan("httpasyncclient/HttpAsyncRequestExecutor:"); + stateInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentsType, null); + stateInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentsType, httpResponse); + processResponseInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentsType, null); + processResponseInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentsType, httpResponse); + Assert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + + List spans = SegmentHelper.getSpans(traceSegment); + assertHttpSpan(spans.get(0)); + verify(request, times(1)).setHeader(anyString(), anyString()); + } + + @Test + public void testStatusCodeNotEquals200() throws Throwable { + when(statusLine.getStatusCode()).thenReturn(500); + AbstractSpan span = ContextManager.createLocalSpan("httpasyncclient/HttpAsyncRequestExecutor:"); + stateInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentsType, null); + stateInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentsType, httpResponse); + allArguments = new Object[] {httpResponse}; + setResponseInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentsType, null); + setResponseInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentsType, httpResponse); + processResponseInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentsType, null); + processResponseInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentsType, httpResponse); + + Assert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + + assertThat(spans.size(), is(3)); + + List tags = SpanHelper.getTags(spans.get(0)); + assertThat(tags.size(), is(3)); + assertThat(tags.get(2).getValue(), is("500")); + + assertHttpSpan(spans.get(0)); + assertThat(SpanHelper.getErrorOccurred(spans.get(0)), is(true)); + verify(request, times(1)).setHeader(anyString(), anyString()); + } + + private void assertHttpSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), is("/test-web/httpasync")); + assertThat(SpanHelper.getComponentId(span), is(26)); + List tags = SpanHelper.getTags(span); + assertThat(tags.get(0).getValue(), is("http://127.0.0.1:8080/test-web/httpasync")); + assertThat(tags.get(1).getValue(), is("GET")); + assertThat(span.isExit(), is(true)); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/TestException.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/TestException.java new file mode 100644 index 0000000000000000000000000000000000000000..992300156539b7972f504d7c20af77898b293f80 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/TestException.java @@ -0,0 +1,160 @@ +/* + * 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.httpasyncclient.v4; + +import java.util.List; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.ProtocolVersion; +import org.apache.http.RequestLine; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.hamcrest.CoreMatchers; +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.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.LogDataEntity; +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.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.TracingSegmentRunner; + +import static junit.framework.TestCase.assertNotNull; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @auther lytscu + */ +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +@PrepareForTest(HttpHost.class) +public class TestException { + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule agentServiceRule = new AgentServiceRule(); + + private StateInterceptor stateInterceptor; + + private SetResponseInterceptor setResponseInterceptor; + + private ProcessResponseInterceptor processResponseInterceptor; + @Mock + private HttpHost httpHost; + @Mock + private HttpRequestWrapper request; + @Mock + private HttpRequest httpRequest; + @Mock + private HttpResponse httpResponse; + @Mock + private StatusLine statusLine; + + private Object[] allArguments, setResponseInterceptorArguments; + private Class[] argumentsType; + + @Mock + private EnhancedInstance enhancedInstance; + + @Before + public void setUp() throws Exception { + ServiceManager.INSTANCE.boot(); + stateInterceptor = new StateInterceptor(); + setResponseInterceptor = new SetResponseInterceptor(); + processResponseInterceptor = new ProcessResponseInterceptor(); + PowerMockito.mock(HttpHost.class); + when(statusLine.getStatusCode()).thenReturn(200); + when(httpResponse.getStatusLine()).thenReturn(statusLine); + when(httpHost.getHostName()).thenReturn("127.0.0.1"); + when(httpHost.getSchemeName()).thenReturn("http"); + when(request.getOriginal()).thenReturn(httpRequest); + when(httpRequest.getRequestLine()).thenReturn(new RequestLine() { + @Override + public String getMethod() { + return "GET"; + } + + @Override + public ProtocolVersion getProtocolVersion() { + return new ProtocolVersion("http", 1, 1); + } + + @Override + public String getUri() { + return "http://127.0.0.1:8080/test-web/httpasync"; + } + }); + when(httpHost.getPort()).thenReturn(8080); + + allArguments = new Object[] {request}; + setResponseInterceptorArguments = new Object[] {httpResponse}; + argumentsType = new Class[] {request.getClass()}; + } + + @Test + public void testHttpClientWithException() throws Throwable { + AbstractSpan localSpan = ContextManager.createLocalSpan("httpasyncclient/HttpAsyncRequestExecutor:"); + stateInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentsType, null); + stateInterceptor.handleMethodException(enhancedInstance, null, allArguments, argumentsType, new RuntimeException("testException")); + processResponseInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentsType, null); + processResponseInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentsType, httpResponse); + Assert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + + assertThat(spans.size(), is(3)); + AbstractTracingSpan span = spans.get(0); + assertThat(SpanHelper.getErrorOccurred(span), is(true)); + assertHttpSpanErrorLog(SpanHelper.getLogs(span)); + verify(request, times(1)).setHeader(anyString(), anyString()); + + } + + private void assertHttpSpanErrorLog(List logs) { + assertThat(logs.size(), is(1)); + LogDataEntity logData = logs.get(0); + Assert.assertThat(logData.getLogs().size(), is(4)); + Assert.assertThat(logData.getLogs().get(0).getValue(), CoreMatchers.is("error")); + Assert.assertThat(logData.getLogs().get(1).getValue(), CoreMatchers.is(RuntimeException.class.getName())); + Assert.assertThat(logData.getLogs().get(2).getValue(), is("testException")); + assertNotNull(logData.getLogs().get(3).getValue()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 0bba88f186d129e7814ba0b6c5dc50b235b49793..4b81d1d8cd7317582c467e7611fc5a1fb7b9d2ec 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -52,6 +52,7 @@ rocketMQ-4.x-plugin elastic-job-2.x-plugin mongodb-2.x-plugin + httpasyncclient-4.x-plugin pom diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/MessageSendInterceptor.java b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/MessageSendInterceptor.java index 05eadfc52ea6d3626874727f93b53811ff896081..b392fcb65c1ae84d3b3c8394a9dd8c0ad51146d4 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/MessageSendInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/MessageSendInterceptor.java @@ -20,12 +20,12 @@ package org.apache.skywalking.apm.plugin.rocketMQ.v4; import java.lang.reflect.Method; -import org.apache.rocketmq.client.impl.CommunicationMode; import org.apache.rocketmq.common.message.Message; import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeader; 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; @@ -60,10 +60,9 @@ public class MessageSendInterceptor implements InstanceMethodsAroundInterceptor String namingServiceAddress = String.valueOf(objInst.getSkyWalkingDynamicField()); AbstractSpan span = ContextManager.createExitSpan(buildOperationName(message.getTopic()), contextCarrier, namingServiceAddress); span.setComponent(ComponentsDefine.ROCKET_MQ); + Tags.MQ_BROKER.set(span, (String)allArguments[0]); + Tags.MQ_TOPIC.set(span, message.getTopic()); SpanLayer.asMQ(span); - span.tag("brokerName", (String)allArguments[1]); - span.tag("tags", message.getTags()); - span.tag("communication.mode", ((CommunicationMode)allArguments[5]).name()); SendMessageRequestHeader requestHeader = (SendMessageRequestHeader)allArguments[3]; StringBuilder properties = new StringBuilder(requestHeader.getProperties()); diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/MessageSendInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/MessageSendInterceptorTest.java index c9abeb57bb4d157d1778ffdb8a1c8576942e8047..52e32963b9dca946ebb1deaad0a95a96d2947a7a 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/MessageSendInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/MessageSendInterceptorTest.java @@ -110,8 +110,7 @@ public class MessageSendInterceptorTest { SpanAssert.assertLayer(mqSpan, SpanLayer.MQ); SpanAssert.assertComponent(mqSpan, ComponentsDefine.ROCKET_MQ); - SpanAssert.assertTag(mqSpan, 0, "test"); - SpanAssert.assertTag(mqSpan, 1, "TagA"); + SpanAssert.assertTag(mqSpan, 0, "127.0.0.1"); verify(messageRequestHeader, times(1)).setProperties(anyString()); verify(callBack, times(1)).setSkyWalkingDynamicField(Matchers.any()); } @@ -130,8 +129,7 @@ public class MessageSendInterceptorTest { SpanAssert.assertLayer(mqSpan, SpanLayer.MQ); SpanAssert.assertComponent(mqSpan, ComponentsDefine.ROCKET_MQ); - SpanAssert.assertTag(mqSpan, 0, "test"); - SpanAssert.assertTag(mqSpan, 1, "TagA"); + SpanAssert.assertTag(mqSpan, 0, "127.0.0.1"); verify(messageRequestHeader, times(1)).setProperties(anyString()); }