From f9a2e64a0d06c1d2d191b9b0eb145c22ffda3ef3 Mon Sep 17 00:00:00 2001 From: Minwoo Jung Date: Wed, 11 Mar 2015 17:04:51 +0900 Subject: [PATCH 1/9] [#143] try & situate button position. --- .../scripts/directives/distributedCallFlow.js | 28 +++++++++---------- .../scripts/directives/transactionTable.js | 2 ++ .../main/webapp/views/transactionTable.html | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/web/src/main/webapp/scripts/directives/distributedCallFlow.js b/web/src/main/webapp/scripts/directives/distributedCallFlow.js index 689e27c1c..0567c78a7 100644 --- a/web/src/main/webapp/scripts/directives/distributedCallFlow.js +++ b/web/src/main/webapp/scripts/directives/distributedCallFlow.js @@ -16,8 +16,8 @@ pinpointApp.directive('distributedCallFlow', [ '$filter', '$timeout', // initialize variables of methods var initialize, treeFormatter, treeFilter, parseData, execTimeFormatter, - getColorByString, progressBarFormatter, argumentFormatter, hasChildNode; - //getColorByString, progressBarFormatter, argumentFormatter, linkFormatter, hasChildNode; +// getColorByString, progressBarFormatter, argumentFormatter, hasChildNode; + getColorByString, progressBarFormatter, argumentFormatter, linkFormatter, hasChildNode; // bootstrap window.callStacks = []; // Due to Slick.Data.DataView, must use window property to resolve scope-related problems. @@ -125,14 +125,14 @@ pinpointApp.directive('distributedCallFlow', [ '$filter', '$timeout', }; - //linkFormatter = function (row, cell, value, columnDef, dataConrtext) { - // var html = []; - // html.push('nelo'); - // return html.join(''); - //}; + linkFormatter = function (row, cell, value, columnDef, dataConrtext) { + var html = []; + html.push('nelo'); + return html.join(''); + }; /** * exec time formatter @@ -182,8 +182,8 @@ pinpointApp.directive('distributedCallFlow', [ '$filter', '$timeout', {id: "class", name: "Class", field: "class", width: 120}, {id: "api-type", name: "Api Type", field: "apiType", width: 90}, {id: "agent", name: "Agent", field: "agent", width: 130}, - {id: "application-name", name: "Application Name", field: "applicationName", width: 150}//, - //{id: "Loglink", name: "log", field: "logLink", width: 50, formatter:linkFormatter} + {id: "application-name", name: "Application Name", field: "applicationName", width: 150}, + {id: "Loglink", name: "log", field: "logLink", width: 50, formatter:linkFormatter} ]; /** @@ -211,8 +211,8 @@ pinpointApp.directive('distributedCallFlow', [ '$filter', '$timeout', agent: val[index['agent']], applicationName: val[index['applicationName']], hasException: val[index['hasException']], - isMethod: val[index['isMethod']] //, - //logLink : "http://localhost/urllogLink/" + isMethod: val[index['isMethod']] , + logLink : "http://localhost/NeloLogWithTransactionId.pinpoint?transactionId=minwoo_local_tomcat%5E1425368654938%5E10" }); }); return result; diff --git a/web/src/main/webapp/scripts/directives/transactionTable.js b/web/src/main/webapp/scripts/directives/transactionTable.js index 30a38b39d..bfd0b484c 100644 --- a/web/src/main/webapp/scripts/directives/transactionTable.js +++ b/web/src/main/webapp/scripts/directives/transactionTable.js @@ -45,6 +45,8 @@ pinpointApp.directive('transactionTable', ['$window', function ($window) { var index = 1; angular.forEach(scope.transactionList, function (val, key) { val['index'] = index++; + val['logName'] = "nelo"; + val['logUrl'] = "http://localhost/NeloLogWithTransactionId.pinpoint?transactionId=minwoo_local_tomcat%5E1425368654938%5E10"; }); }; diff --git a/web/src/main/webapp/views/transactionTable.html b/web/src/main/webapp/views/transactionTable.html index 0da9ffbcb..3f663d04e 100644 --- a/web/src/main/webapp/views/transactionTable.html +++ b/web/src/main/webapp/views/transactionTable.html @@ -66,7 +66,7 @@ {{transaction.agentId}} {{transaction.remoteAddr}} - {{transaction.traceId}} + {{transaction.traceId}} {{transaction.logName}} From c97e66edce2bae0efe6b68b192a60ccbf8161ac8 Mon Sep 17 00:00:00 2001 From: Minwoo Jung Date: Tue, 17 Mar 2015 15:48:14 +0900 Subject: [PATCH 2/9] [#234] Add function to see log of application using pinpoint agent --- .../profiler/modifier/log/MdcKey.java | 3 +- .../LoggingEventOfLog4jInterceptor.java | 2 + .../LoggingEventOfLogbackInterceptor.java | 2 + .../BusinessTransactionController.java | 30 ++++-- .../controller/ScatterChartController.java | 18 +++- .../service/TransactionInfoServiceImpl.java | 102 ++++++++++++++++-- .../pinpoint/web/vo/callstacks/Record.java | 36 ++++++- .../main/resources/pinpoint-web.properties | 7 +- .../WEB-INF/views/transactionInfoJson.jsp | 19 +++- .../WEB-INF/views/transactionmetadata.jsp | 9 +- .../scripts/directives/distributedCallFlow.js | 53 +++++---- .../scripts/directives/transactionTable.js | 2 - .../main/webapp/views/transactionTable.html | 2 +- 13 files changed, 238 insertions(+), 47 deletions(-) diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/MdcKey.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/MdcKey.java index 8e2086d2c..153898b9a 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/MdcKey.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/MdcKey.java @@ -19,5 +19,6 @@ package com.navercorp.pinpoint.profiler.modifier.log; * @author minwoo.jung */ public class MdcKey { - public static final String TRANSACTION_ID = "TransactionID"; + public static final String TRANSACTION_ID = "PtransactionId"; + public static final String SPAN_ID = "PspanId"; } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/log4j/interceptor/LoggingEventOfLog4jInterceptor.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/log4j/interceptor/LoggingEventOfLog4jInterceptor.java index 5f2d6f957..39ed1d2ba 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/log4j/interceptor/LoggingEventOfLog4jInterceptor.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/log4j/interceptor/LoggingEventOfLog4jInterceptor.java @@ -46,9 +46,11 @@ public class LoggingEventOfLog4jInterceptor implements SimpleAroundInterceptor, if (trace == null) { MDC.remove(MdcKey.TRANSACTION_ID); + MDC.remove(MdcKey.SPAN_ID); return; } else { MDC.put(MdcKey.TRANSACTION_ID, trace.getTraceId().getTransactionId()); + MDC.put(MdcKey.SPAN_ID, String.valueOf(trace.getTraceId().getSpanId())); } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/logback/interceptor/LoggingEventOfLogbackInterceptor.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/logback/interceptor/LoggingEventOfLogbackInterceptor.java index b23e8824f..09a445b8f 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/logback/interceptor/LoggingEventOfLogbackInterceptor.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/log/logback/interceptor/LoggingEventOfLogbackInterceptor.java @@ -46,9 +46,11 @@ public class LoggingEventOfLogbackInterceptor implements SimpleAroundInterceptor if (trace == null) { MDC.remove(MdcKey.TRANSACTION_ID); + MDC.remove(MdcKey.SPAN_ID); return; } else { MDC.put(MdcKey.TRANSACTION_ID, trace.getTraceId().getTransactionId()); + MDC.put(MdcKey.SPAN_ID, String.valueOf(trace.getTraceId().getSpanId())); } } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/controller/BusinessTransactionController.java b/web/src/main/java/com/navercorp/pinpoint/web/controller/BusinessTransactionController.java index 015af8204..6527ffd6c 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/controller/BusinessTransactionController.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/controller/BusinessTransactionController.java @@ -18,10 +18,24 @@ package com.navercorp.pinpoint.web.controller; import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + import com.navercorp.pinpoint.web.applicationmap.ApplicationMap; import com.navercorp.pinpoint.web.calltree.span.SpanAlign; import com.navercorp.pinpoint.web.filter.Filter; @@ -36,19 +50,9 @@ import com.navercorp.pinpoint.web.vo.BusinessTransactions; import com.navercorp.pinpoint.web.vo.LimitedScanResult; import com.navercorp.pinpoint.web.vo.Range; import com.navercorp.pinpoint.web.vo.TransactionId; +import com.navercorp.pinpoint.web.vo.callstacks.Record; import com.navercorp.pinpoint.web.vo.callstacks.RecordSet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.servlet.ModelAndView; - /** * @author emeroad */ @@ -68,6 +72,9 @@ public class BusinessTransactionController { @Autowired private FilterBuilder filterBuilder; + + @Value("#{pinpointWebProps['log.enable'] ?: false}") + private boolean logLinkEnable; /** * executed URLs in applicationname query within from ~ to timeframe @@ -164,6 +171,7 @@ public class BusinessTransactionController { ApplicationMap map = filteredMapService.selectApplicationMap(traceId); mv.addObject("nodes", map.getNodes()); mv.addObject("links", map.getLinks()); + mv.addObject("logLinkEnable", logLinkEnable); // call stacks RecordSet recordSet = this.transactionInfoService.createRecordSet(spanAligns, focusTimestamp); diff --git a/web/src/main/java/com/navercorp/pinpoint/web/controller/ScatterChartController.java b/web/src/main/java/com/navercorp/pinpoint/web/controller/ScatterChartController.java index 86ae08b4f..2da2bb419 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/controller/ScatterChartController.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/controller/ScatterChartController.java @@ -38,6 +38,7 @@ import com.navercorp.pinpoint.web.vo.scatter.ScatterIndex; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.StopWatch; @@ -64,6 +65,16 @@ public class ScatterChartController { @Autowired private FilterBuilder filterBuilder; + + + @Value("#{pinpointWebProps['log.enable'] ?: false}") + private boolean logLinkEnable; + + @Value("#{pinpointWebProps['log.button.name'] ?: ''}") + private String logButtonName; + + @Value("#{pinpointWebProps['log.page.url'] ?: ''}") + private String logPageUrl; private static final String PREFIX_TRANSACTION_ID = "I"; private static final String PREFIX_TIME = "T"; @@ -222,7 +233,12 @@ public class ScatterChartController { List metadata = scatter.selectTransactionMetadata(query); model.addAttribute("metadata", metadata); } - + + if (logLinkEnable) { + model.addAttribute("logButtonName", logButtonName); + model.addAttribute("logPageUrl", logPageUrl); + } + return "transactionmetadata"; } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/TransactionInfoServiceImpl.java b/web/src/main/java/com/navercorp/pinpoint/web/service/TransactionInfoServiceImpl.java index 09250d1e2..aa5744dc5 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/TransactionInfoServiceImpl.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/TransactionInfoServiceImpl.java @@ -18,6 +18,8 @@ package com.navercorp.pinpoint.web.service; import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import com.navercorp.pinpoint.common.AnnotationKey; @@ -68,6 +70,15 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { @Autowired private AnnotationKeyRegistryService annotationKeyRegistryService; + @Value("#{pinpointWebProps['log.enable'] ?: false}") + private boolean logLinkEnable; + + @Value("#{pinpointWebProps['log.button.name'] ?: ''}") + private String logButtonName; + + @Value("#{pinpointWebProps['log.page.url'] ?: ''}") + private String logPageUrl; + @Override public BusinessTransactions selectBusinessTransactions(List transactionIdList, String applicationName, Range range, Filter filter) { if (transactionIdList == null) { @@ -153,6 +164,11 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { } recordSet.setRecordList(recordList); + + if (logLinkEnable) { + addlogLink(recordSet); + } + return recordSet; } @@ -165,6 +181,66 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { } } + private void addlogLink(RecordSet recordSet) { + List records = recordSet.getRecordList(); + List transactionInfoes = new LinkedList(); + + for (Iterator iterator = records.iterator(); iterator.hasNext();) { + Record record = (Record) iterator.next(); + + if(record.getTransactionId() == null) { + continue; + } + + TransactionInfo transactionInfo = new TransactionInfo(record.getTransactionId(), record.getSpanId()); + + if (transactionInfoes.contains(transactionInfo)) { + continue; + }; + + record.setLogPageUrl(logPageUrl); + record.setLogButtonName(logButtonName); + + transactionInfoes.add(transactionInfo); + } + } + + private class TransactionInfo { + + private final String transactionId; + private final long spanId; + + public TransactionInfo(String transactionId, long spanId) { + this.transactionId = transactionId; + this.spanId = spanId; + } + + public String getTransactionId() { + return transactionId; + } + + public long getSpanId() { + return spanId; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TransactionInfo == false) { + return false; + } + + TransactionInfo transactionInfo = (TransactionInfo)obj; + + if (!transactionId.equals(transactionInfo.getTransactionId())) { + return false; + } + if (spanId != transactionInfo.getSpanId()) { + return false; + } + + return true; + } + } private long getStartTime(List spanAlignList) { if (spanAlignList == null || spanAlignList.size() == 0) { @@ -314,7 +390,9 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { registry.findServiceType(spanBo.getServiceType()), null, spanAlign.isHasChild(), - false); + false, + spanBo.getTransactionId(), + spanBo.getSpanId()); record.setSimpleClassName(apiDescription.getSimpleClassName()); record.setFullApiDescription(method); recordList.add(record); @@ -334,7 +412,9 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { registry.findServiceType(spanBo.getServiceType()), null, spanAlign.isHasChild(), - false); + false, + spanBo.getTransactionId(), + spanBo.getSpanId()); record.setSimpleClassName(""); record.setFullApiDescription(""); recordList.add(record); @@ -388,7 +468,9 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { /* spanEventBo.getDestinationId(), spanEventBo.getServiceTypeCode(),*/ destinationId, spanAlign.isHasChild(), - false); + false, + spanBo.getTransactionId(), + spanBo.getSpanId()); record.setSimpleClassName(apiDescription.getSimpleClassName()); record.setFullApiDescription(method); @@ -416,7 +498,9 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { /*spanEventBo.getDestinationId(), spanEventBo.getServiceTypeCode(),*/ destinationId, spanAlign.isHasChild(), - false); + false, + spanBo.getTransactionId(), + spanBo.getSpanId()); record.setSimpleClassName(""); record.setFullApiDescription(method); @@ -454,7 +538,9 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { null, null, false, - false); + false, + spanBo.getTransactionId(), + spanBo.getSpanId()); } } else { final SpanEventBo spanEventBo = spanAlign.getSpanEventBo(); @@ -474,7 +560,9 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { null, null, false, - true); + true, + null, + 0); } } return null; @@ -529,7 +617,7 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { for (AnnotationBo ann : annotationBoList) { AnnotationKey annotation = findAnnotationKey(ann.getKey()); if (annotation.isViewInRecordSet()) { - Record record = new Record(depth, getNextId(), parentId, false, annotation.getName(), ann.getValue().toString(), 0L, 0L, 0, null, null, null, null, false, false); + Record record = new Record(depth, getNextId(), parentId, false, annotation.getName(), ann.getValue().toString(), 0L, 0L, 0, null, null, null, null, false, false, null, 0); recordList.add(record); } } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/callstacks/Record.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/callstacks/Record.java index 636c37eb4..7747a8cfa 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/vo/callstacks/Record.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/callstacks/Record.java @@ -44,11 +44,18 @@ public class Record { private final String destinationId; private final boolean excludeFromTimeline; + private final String transactionId; + private final long spanId; + private boolean focused; private boolean hasChild; private boolean hasException; + private String logPageUrl; + private String logButtonName; + + - public Record(int tab, int id, int parentId, boolean method, String title, String arguments, long begin, long elapsed, long gap, String agent, String applicationName, ServiceType serviceType, String destinationId, boolean hasChild, boolean hasException) { + public Record(int tab, int id, int parentId, boolean method, String title, String arguments, long begin, long elapsed, long gap, String agent, String applicationName, ServiceType serviceType, String destinationId, boolean hasChild, boolean hasException, String transactionId, long spanId) { this.tab = tab; this.id = id; this.parentId = parentId; @@ -68,6 +75,9 @@ public class Record { this.excludeFromTimeline = serviceType == null || serviceType.isInternalMethod(); this.hasChild = hasChild; this.hasException = hasException; + + this.transactionId = transactionId; + this.spanId = spanId; } public int getId() { @@ -175,6 +185,30 @@ public class Record { public boolean getHasException() { return hasException; } + + public String getTransactionId() { + return transactionId; + } + + public long getSpanId() { + return spanId; + } + + public void setLogPageUrl(String logPageUrl) { + this.logPageUrl = logPageUrl; + } + + public void setLogButtonName(String logButtonName) { + this.logButtonName = logButtonName; + } + + public String getLogPageUrl() { + return this.logPageUrl; + } + + public String getLogButtonName() { + return this.logButtonName; + } @Override diff --git a/web/src/main/resources/pinpoint-web.properties b/web/src/main/resources/pinpoint-web.properties index 51604645c..550306ee8 100644 --- a/web/src/main/resources/pinpoint-web.properties +++ b/web/src/main/resources/pinpoint-web.properties @@ -6,4 +6,9 @@ cluster.zookeeper.sessiontimeout=3000 cluster.zookeeper.retry.interval=5000 # FIXME - should be removed for proper authentication -admin.password=admin \ No newline at end of file +admin.password=admin + +#log site link +#log.enable=false +#log.page.url= +#log.button.name= diff --git a/web/src/main/webapp/WEB-INF/views/transactionInfoJson.jsp b/web/src/main/webapp/WEB-INF/views/transactionInfoJson.jsp index dafdc2cc8..dd7b2c4a3 100644 --- a/web/src/main/webapp/WEB-INF/views/transactionInfoJson.jsp +++ b/web/src/main/webapp/WEB-INF/views/transactionInfoJson.jsp @@ -10,6 +10,7 @@ "callStackStart" : ${callstackStart}, "callStackEnd" : ${callstackEnd}, "completeState" : "${completeState}", + "logLinkEnable" : ${logLinkEnable}, "callStackIndex" : { "depth":0, "begin":1, @@ -31,7 +32,9 @@ "apiType":17, "agent":18, "isFocused":19, - "hasException":20 + "hasException":20, + "logButtonName":21, + "logPageUrl":22 }, "callStack" : [ [ @@ -55,7 +58,19 @@ ${record.hasChild}, "${record.apiType}", "${record.agent}", ${record.focused}, -${record.hasException} +${record.hasException}, +"${record.logButtonName}", + + + + + + + + "${logPageUrl}" + + "" + ], ], "applicationMapData" : { diff --git a/web/src/main/webapp/WEB-INF/views/transactionmetadata.jsp b/web/src/main/webapp/WEB-INF/views/transactionmetadata.jsp index bfa3b9a67..1386f815e 100644 --- a/web/src/main/webapp/WEB-INF/views/transactionmetadata.jsp +++ b/web/src/main/webapp/WEB-INF/views/transactionmetadata.jsp @@ -13,7 +13,14 @@ "agentId" : "${span.agentId}", "endpoint" : "${span.endPoint}", "exception" : ${span.errCode}, - "remoteAddr" : "${span.remoteAddr}" + "remoteAddr" : "${span.remoteAddr}", + "logButtonName" : "${logButtonName}", + + + + + "logPageUrl" : "${url}" + } , diff --git a/web/src/main/webapp/scripts/directives/distributedCallFlow.js b/web/src/main/webapp/scripts/directives/distributedCallFlow.js index 0567c78a7..4be3976d1 100644 --- a/web/src/main/webapp/scripts/directives/distributedCallFlow.js +++ b/web/src/main/webapp/scripts/directives/distributedCallFlow.js @@ -12,7 +12,7 @@ pinpointApp.directive('distributedCallFlow', [ '$filter', '$timeout', link: function postLink(scope, element, attrs) { // initialize variables - var grid, columns, dataView, lastAgent; + var grid, dataView, lastAgent; // initialize variables of methods var initialize, treeFormatter, treeFilter, parseData, execTimeFormatter, @@ -125,12 +125,24 @@ pinpointApp.directive('distributedCallFlow', [ '$filter', '$timeout', }; - linkFormatter = function (row, cell, value, columnDef, dataConrtext) { + linkFormatter = function (row, cell, value, columnDef, dataContext) { + + if (!value || 0 === value.length) { + return; + } + var html = []; html.push('nelo'); + html.push('" target="_blank">'); + + var item = dataView.getItemById(dataContext.id); + var logButtonName = item.logButtonName; + html.push(logButtonName); + + html.push(''); + return html.join(''); }; @@ -171,21 +183,6 @@ pinpointApp.directive('distributedCallFlow', [ '$filter', '$timeout', return ""; }; - // columns - columns = [ - {id: "method", name: "Method", field: "method", width: 400, formatter: treeFormatter}, - {id: "argument", name: "Argument", field: "argument", width: 300, formatter: argumentFormatter}, - {id: "exec-time", name: "Exec Time", field: "execTime", width: 90, formatter: execTimeFormatter}, - {id: "gap-ms", name: "Gap(ms)", field: "gapMs", width: 60, cssClass: "right-align"}, - {id: "time-ms", name: "Time(ms)", field: "timeMs", width: 60, cssClass: "right-align"}, - {id: "time-per", name: "Time(%)", field: "timePer", width: 100, formatter: progressBarFormatter}, - {id: "class", name: "Class", field: "class", width: 120}, - {id: "api-type", name: "Api Type", field: "apiType", width: 90}, - {id: "agent", name: "Agent", field: "agent", width: 130}, - {id: "application-name", name: "Application Name", field: "applicationName", width: 150}, - {id: "Loglink", name: "log", field: "logLink", width: 50, formatter:linkFormatter} - ]; - /** * parse data * @param index @@ -212,7 +209,8 @@ pinpointApp.directive('distributedCallFlow', [ '$filter', '$timeout', applicationName: val[index['applicationName']], hasException: val[index['hasException']], isMethod: val[index['isMethod']] , - logLink : "http://localhost/NeloLogWithTransactionId.pinpoint?transactionId=minwoo_local_tomcat%5E1425368654938%5E10" + logLink : val[index['logPageUrl']], + logButtonName : val[index['logButtonName']], }); }); return result; @@ -253,6 +251,23 @@ pinpointApp.directive('distributedCallFlow', [ '$filter', '$timeout', // }; dataView.endUpdate(); + var columns = [ + {id: "method", name: "Method", field: "method", width: 400, formatter: treeFormatter}, + {id: "argument", name: "Argument", field: "argument", width: 300, formatter: argumentFormatter}, + {id: "exec-time", name: "Exec Time", field: "execTime", width: 90, formatter: execTimeFormatter}, + {id: "gap-ms", name: "Gap(ms)", field: "gapMs", width: 60, cssClass: "right-align"}, + {id: "time-ms", name: "Time(ms)", field: "timeMs", width: 60, cssClass: "right-align"}, + {id: "time-per", name: "Time(%)", field: "timePer", width: 100, formatter: progressBarFormatter}, + {id: "class", name: "Class", field: "class", width: 120}, + {id: "api-type", name: "Api Type", field: "apiType", width: 90}, + {id: "agent", name: "Agent", field: "agent", width: 130}, + {id: "application-name", name: "Application Name", field: "applicationName", width: 150} + ]; + + if (t.logLinkEnable) { + columns.push({id: "Loglink", name: "log", field: "logLink", width: 50, formatter:linkFormatter}); + } + grid = new Slick.Grid(element.get(0), dataView, columns, options); var isSingleClick = true, clickTimeout = false; diff --git a/web/src/main/webapp/scripts/directives/transactionTable.js b/web/src/main/webapp/scripts/directives/transactionTable.js index bfd0b484c..30a38b39d 100644 --- a/web/src/main/webapp/scripts/directives/transactionTable.js +++ b/web/src/main/webapp/scripts/directives/transactionTable.js @@ -45,8 +45,6 @@ pinpointApp.directive('transactionTable', ['$window', function ($window) { var index = 1; angular.forEach(scope.transactionList, function (val, key) { val['index'] = index++; - val['logName'] = "nelo"; - val['logUrl'] = "http://localhost/NeloLogWithTransactionId.pinpoint?transactionId=minwoo_local_tomcat%5E1425368654938%5E10"; }); }; diff --git a/web/src/main/webapp/views/transactionTable.html b/web/src/main/webapp/views/transactionTable.html index 3f663d04e..fdd422558 100644 --- a/web/src/main/webapp/views/transactionTable.html +++ b/web/src/main/webapp/views/transactionTable.html @@ -66,7 +66,7 @@ {{transaction.agentId}} {{transaction.remoteAddr}} - {{transaction.traceId}} {{transaction.logName}} + {{transaction.traceId}} {{transaction.logButtonName}} From e7c06d4a94c5713738e0bdbb9889e048c24f2965 Mon Sep 17 00:00:00 2001 From: Minwoo Jung Date: Fri, 20 Mar 2015 14:39:34 +0900 Subject: [PATCH 3/9] [#134] edit code creating record class --- .../pinpoint/web/service/TransactionInfoServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/TransactionInfoServiceImpl.java b/web/src/main/java/com/navercorp/pinpoint/web/service/TransactionInfoServiceImpl.java index aa5744dc5..5771c1172 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/TransactionInfoServiceImpl.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/TransactionInfoServiceImpl.java @@ -48,6 +48,7 @@ import org.apache.commons.lang.ObjectUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; /** @@ -626,7 +627,7 @@ public class TransactionInfoServiceImpl implements TransactionInfoService { } private Record createParameterRecord(int depth, int parentId, String method, String argument) { - return new Record(depth, getNextId(), parentId, false, method, argument, 0L, 0L, 0, null, null, null, null, false, false); + return new Record(depth, getNextId(), parentId, false, method, argument, 0L, 0L, 0, null, null, null, null, false, false, null, 0); } } From 3113fe4f469408a737538f6df748bb2302a049f3 Mon Sep 17 00:00:00 2001 From: HyunGil Jeong Date: Fri, 27 Feb 2015 10:32:57 +0900 Subject: [PATCH 4/9] [#195] implemented application type detector --- agent/src/main/resources/pinpoint.config | 6 +- .../pinpoint-spring-bean-test.config | 6 +- .../bootstrap/config/ProfilerConfig.java | 24 +- .../bootstrap/plugin/ServerTypeDetector.java | 29 +- .../ApplicationServerTypePluginResolver.java | 72 ++++ .../bootstrap/resolver/ConditionProvider.java | 84 ++++ .../resolver/condition/Condition.java | 26 ++ .../resolver/condition/ConditionValue.java | 26 ++ .../condition/LibraryClassCondition.java | 54 +++ .../condition/MainClassCondition.java | 107 +++++ .../condition/SystemPropertyCondition.java | 68 +++ .../condition/MainClassConditionTest.java | 147 +++++++ .../SystemPropertyConditionTest.java | 146 +++++++ .../common/util/SystemPropertyKey.java | 3 +- .../plugin/tomcat/TomcatDetector.java | 47 +-- .../tomcat/src/test/resources/pinpoint.config | 4 + .../pinpoint/profiler/DefaultAgent.java | 10 +- .../util/ApplicationServerTypeResolver.java | 91 ++-- .../pinpoint-spring-bean-test.config | 398 +++++++++--------- profiler/src/test/resources/pinpoint.config | 6 +- 20 files changed, 1058 insertions(+), 296 deletions(-) create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ApplicationServerTypePluginResolver.java create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProvider.java create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/Condition.java create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/ConditionValue.java create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/LibraryClassCondition.java create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassCondition.java create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyCondition.java create mode 100644 bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassConditionTest.java create mode 100644 bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyConditionTest.java diff --git a/agent/src/main/resources/pinpoint.config b/agent/src/main/resources/pinpoint.config index 1232c4470..5d6f4dada 100644 --- a/agent/src/main/resources/pinpoint.config +++ b/agent/src/main/resources/pinpoint.config @@ -56,6 +56,10 @@ profiler.tcpdatasender.command.accept.enable=true #profiler.applicationservertype=TOMCAT #profiler.applicationservertype=BLOC +########################################################### +# application type detect order # +########################################################### +profiler.type.detect.order= ########################################################### # user defined classes # @@ -216,4 +220,4 @@ profiler.log4j.logging.transactioninfo=false ########################################################### # logback ########################################################### -profiler.logback.logging.transactioninfo=false \ No newline at end of file +profiler.logback.logging.transactioninfo=false diff --git a/agent/src/test/resources/pinpoint-spring-bean-test.config b/agent/src/test/resources/pinpoint-spring-bean-test.config index 3c787b397..5f6a9def2 100644 --- a/agent/src/test/resources/pinpoint-spring-bean-test.config +++ b/agent/src/test/resources/pinpoint-spring-bean-test.config @@ -56,6 +56,10 @@ profiler.tcpdatasender.command.accept.enable=true #profiler.applicationservertype=TOMCAT #profiler.applicationservertype=BLOC +########################################################### +# application type detect order # +########################################################### +profiler.type.detect.order= ########################################################### # user defined classes # @@ -194,4 +198,4 @@ profiler.log4j.logging.transactioninfo=false ########################################################### # logback ########################################################### -profiler.logback.logging.transactioninfo=false \ No newline at end of file +profiler.logback.logging.transactioninfo=false diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/config/ProfilerConfig.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/config/ProfilerConfig.java index bf63f9344..36dac5b80 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/config/ProfilerConfig.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/config/ProfilerConfig.java @@ -18,11 +18,13 @@ package com.navercorp.pinpoint.bootstrap.config; import com.navercorp.pinpoint.bootstrap.util.NumberUtils; import com.navercorp.pinpoint.bootstrap.util.spring.PropertyPlaceholderHelper; -import com.navercorp.pinpoint.common.ServiceType; import com.navercorp.pinpoint.common.util.PropertyUtils; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; @@ -210,6 +212,7 @@ public class ProfilerConfig { private long agentInfoSendRetryInterval = DEFAULT_AGENT_INFO_SEND_RETRY_INTERVAL; private String applicationServerType; + private List applicationTypeDetectOrder = Collections.emptyList(); private boolean log4jLoggingTransactionInfo; private boolean logbackLoggingTransactionInfo; @@ -589,6 +592,10 @@ public class ProfilerConfig { public Filter getProfilableClassFilter() { return profilableClassFilter; } + + public List getApplicationTypeDetectOrder() { + return applicationTypeDetectOrder; + } public String getApplicationServerType() { return applicationServerType; @@ -768,8 +775,10 @@ public class ProfilerConfig { this.agentInfoSendRetryInterval = readLong("profiler.agentInfo.send.retry.interval", DEFAULT_AGENT_INFO_SEND_RETRY_INTERVAL); // service type - this.applicationServerType = readString("profiler.applicationservertype", ServiceType.STAND_ALONE.getName()); + this.applicationServerType = readString("profiler.applicationservertype", null); + // application type detector order + this.applicationTypeDetectOrder = readTypeDetectOrder("profiler.type.detect.order"); // TODO have to remove // profile package included in order to test "call stack view". @@ -836,6 +845,15 @@ public class ProfilerConfig { return result; } + public List readTypeDetectOrder(String propertyName) { + String value = properties.getProperty(propertyName); + if (value == null) { + return Collections.emptyList(); + } + String[] orders = value.trim().split(","); + return Arrays.asList(orders); + } + public boolean readBoolean(String propertyName, boolean defaultValue) { String value = properties.getProperty(propertyName, Boolean.toString(defaultValue)); boolean result = Boolean.parseBoolean(value); @@ -845,7 +863,6 @@ public class ProfilerConfig { return result; } - @Override public String toString() { final StringBuilder sb = new StringBuilder("ProfilerConfig{"); @@ -929,6 +946,7 @@ public class ProfilerConfig { sb.append(", profilableClassFilter=").append(profilableClassFilter); sb.append(", DEFAULT_AGENT_INFO_SEND_RETRY_INTERVAL=").append(DEFAULT_AGENT_INFO_SEND_RETRY_INTERVAL); sb.append(", agentInfoSendRetryInterval=").append(agentInfoSendRetryInterval); + sb.append(", applicationTypeDetectOrder='").append(applicationTypeDetectOrder).append('\''); sb.append(", applicationServerType=").append(applicationServerType); sb.append('}'); return sb.toString(); diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ServerTypeDetector.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ServerTypeDetector.java index d517a0a60..d53952107 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ServerTypeDetector.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ServerTypeDetector.java @@ -14,13 +14,36 @@ */ package com.navercorp.pinpoint.bootstrap.plugin; +import com.navercorp.pinpoint.bootstrap.resolver.ConditionProvider; +import com.navercorp.pinpoint.common.ServiceType; /** * @author Jongho Moon + * @author HyunGil Jeong * */ public interface ServerTypeDetector { - public String getServerTypeName(); - public boolean detect(); - public boolean canOverride(String serverType); + + /** + * Returns the {@link ServiceType} representing the current plugin, + * with code in a range corresponding to {@link com.navercorp.pinpoint.common.ServiceTypeCategory#SERVER} + * + * @return the {@link ServiceType} representing the current plugin + * @see ServiceType#isWas() + * @see com.navercorp.pinpoint.common.ServiceTypeCategory#SERVER + */ + public ServiceType getServerType(); + + /** + * Checks whether the provided conditions satisfy the requirements given by the plugins implementing this class. + * + *

This method allows the agent to go through each of the registered plugins with classes implementing this interface, + * checking whether the execution environment satisfies the requirements specified in them, returning true if the + * requirements are satisfied. + * + * @param provider conditions provided by the current application + * @return true if the provided conditions satisfy the requirements, false if otherwise + * @see ConditionProvider + */ + public boolean detect(ConditionProvider provider); } diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ApplicationServerTypePluginResolver.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ApplicationServerTypePluginResolver.java new file mode 100644 index 000000000..78e51366f --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ApplicationServerTypePluginResolver.java @@ -0,0 +1,72 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.bootstrap.resolver; + +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.navercorp.pinpoint.bootstrap.plugin.ServerTypeDetector; +import com.navercorp.pinpoint.common.ServiceType; + +/** + * This class attempts to resolve the current application type through {@link ServerTypeDetector}s. + * The application type is resolved by checking the conditions defined in each of the loaded detector's {@code detect} method. + *

+ * If no match is found, the application type defaults to {@code ServiceType.STAND_ALONE} + * + * @author HyunGil Jeong + */ +public class ApplicationServerTypePluginResolver { + + private final Logger logger = Logger.getLogger(ApplicationServerTypePluginResolver.class.getName()); + + private final List serverTypeDetectors; + + private final ConditionProvider conditionProvider; + + private static final ServiceType DEFAULT_SERVER_TYPE = ServiceType.STAND_ALONE; + + public ApplicationServerTypePluginResolver(List serverTypeDetectors) { + this(serverTypeDetectors, ConditionProvider.DEFAULT_CONDITION_PROVIDER); + } + + public ApplicationServerTypePluginResolver(List serverTypeDetectors, ConditionProvider conditionProvider) { + if (serverTypeDetectors == null) { + throw new IllegalArgumentException("serverTypeDetectors should not be null"); + } + if (conditionProvider == null) { + throw new IllegalArgumentException("conditionProvider should not be null"); + } + this.serverTypeDetectors = serverTypeDetectors; + this.conditionProvider = conditionProvider; + } + + public ServiceType resolve() { + for (ServerTypeDetector currentDetector : this.serverTypeDetectors) { + logger.log(Level.INFO, "Attempting to resolve using " + currentDetector.getClass()); + if (currentDetector.detect(this.conditionProvider)) { + logger.log(Level.INFO, "Match found using " + currentDetector.getClass().getSimpleName()); + return currentDetector.getServerType(); + } else { + logger.log(Level.INFO, "No match found using " + currentDetector.getClass()); + } + } + logger.log(Level.INFO, "Server type not resolved. Defaulting to " + DEFAULT_SERVER_TYPE.getName()); + return DEFAULT_SERVER_TYPE; + } +} diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProvider.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProvider.java new file mode 100644 index 000000000..050d72e1c --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProvider.java @@ -0,0 +1,84 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.bootstrap.resolver; + +import java.util.HashMap; +import java.util.Map; + +import com.navercorp.pinpoint.bootstrap.resolver.condition.Condition; +import com.navercorp.pinpoint.bootstrap.resolver.condition.LibraryClassCondition; +import com.navercorp.pinpoint.bootstrap.resolver.condition.MainClassCondition; +import com.navercorp.pinpoint.bootstrap.resolver.condition.SystemPropertyCondition; + +/** + * @author HyunGil Jeong + */ +public class ConditionProvider { + + public static final ConditionProvider DEFAULT_CONDITION_PROVIDER = new ConditionProvider(); + + private final Map>, Condition> conditions; + + public ConditionProvider() { + this(new HashMap>, Condition>()); + } + + public ConditionProvider(Map>, Condition> conditions) { + this.conditions = conditions; + addDefaultConditions(); + } + + private void addDefaultConditions() { + this.conditions.put(MainClassCondition.class, new MainClassCondition()); + this.conditions.put(SystemPropertyCondition.class, new SystemPropertyCondition()); + this.conditions.put(LibraryClassCondition.class, new LibraryClassCondition()); + } + + public > T getCondition(Class conditionClass) { + @SuppressWarnings("unchecked") + T condition = (T)this.conditions.get(conditionClass); + return condition; + } + + /** + * Returns {@link MainClassCondition} that allows plugins to check for the application's bootstrap main class. + * + * @return the {@link MainClassCondition} + */ + public MainClassCondition getMainClassCondition() { + return (MainClassCondition)this.conditions.get(MainClassCondition.class); + } + + /** + * Returns {@link SystemPropertyCondition} that allows plugins to check for system property keys. + * + * @return the {@link SystemPropertyCondition} + */ + public SystemPropertyCondition getSystemPropertyCondition() { + return (SystemPropertyCondition)this.conditions.get(SystemPropertyCondition.class); + } + + /** + * Returns {@link LibraryClassCondition} that allows plugins to check for classes accessible by + * the system class loader. + * + * @return the {@link LibraryClassCondition} + */ + public LibraryClassCondition getLibraryClassCondition() { + return (LibraryClassCondition)this.conditions.get(LibraryClassCondition.class); + } +} diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/Condition.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/Condition.java new file mode 100644 index 000000000..51f0e5531 --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/Condition.java @@ -0,0 +1,26 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.bootstrap.resolver.condition; + +/** + * @author HyunGil Jeong + */ +public interface Condition { + + public boolean check(T condition); + +} diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/ConditionValue.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/ConditionValue.java new file mode 100644 index 000000000..d05d274bb --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/ConditionValue.java @@ -0,0 +1,26 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.bootstrap.resolver.condition; + +/** + * @author HyunGil Jeong + */ +public interface ConditionValue { + + public V getValue(); + +} diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/LibraryClassCondition.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/LibraryClassCondition.java new file mode 100644 index 000000000..19883464a --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/LibraryClassCondition.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.bootstrap.resolver.condition; + +/** + * Checks whether the specified classes are currently accessible by the System ClassLoader. + * + * @author HyunGil Jeong + */ +public class LibraryClassCondition implements Condition { + + private static final String CLASS_EXTENSION = ".class"; + + private String getClassNameAsResource(String className) { + String classNameAsResource = className.replace('.', '/'); + return classNameAsResource.endsWith(CLASS_EXTENSION) ? classNameAsResource : classNameAsResource.concat(CLASS_EXTENSION); + } + + /** + * Checks if the specified classes can be found in the current System ClassLoader's search path. + * + * @param requiredClasses the fully qualified class names of the classes to check + * @return true if all of the specified classes can be found in the system class loader's search path, + * false if otherwise + */ + @Override + public boolean check(String ... requiredClasses) { + if (requiredClasses == null) { + return false; + } + for (String condition : requiredClasses) { + String classNameAsResource = getClassNameAsResource(condition); + if (ClassLoader.getSystemResource(classNameAsResource) == null) { + return false; + } + } + return true; + } + +} diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassCondition.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassCondition.java new file mode 100644 index 000000000..86ae5b895 --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassCondition.java @@ -0,0 +1,107 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.bootstrap.resolver.condition; + +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.navercorp.pinpoint.common.util.SimpleProperty; +import com.navercorp.pinpoint.common.util.SystemProperty; +import com.navercorp.pinpoint.common.util.SystemPropertyKey; + +/** + * Checks if the application's main class is in one of those specified in {@link MainClassCondition}. + *

+ * The application's main class is extracted by reading the sun.java.command system property, and in cases + * of executable jars, the Main-Class attribute inside the manifest file. + * + * @author HyunGil Jeong + */ +public class MainClassCondition implements Condition, ConditionValue { + + private final Logger logger = Logger.getLogger(MainClassCondition.class.getName()); + + private static final String MANIFEST_MAIN_CLASS_KEY = "Main-Class"; + private static final String NOT_FOUND = null; + + private final String applicationMainClassName; + + public MainClassCondition() { + this(SystemProperty.INSTANCE); + } + + MainClassCondition(SimpleProperty property) { + if (property == null) { + throw new IllegalArgumentException("properties should not be null"); + } + this.applicationMainClassName = getMainClassName(property); + } + + /** + * Checks if the specified value matches the fully qualified class name of the application's main class. + * If the main class cannot be resolved, the method return false. + * + * @param condition the value to check against the application's main class name + * @return true if the specified value matches the name of the main class; + * false if otherwise, or if the main class cannot be resolved + */ + @Override + public boolean check(String condition) { + if (this.applicationMainClassName == NOT_FOUND) { + return false; + } else { + return this.applicationMainClassName.equals(condition); + } + } + + /** + * Returns the fully qualified class name of the application's main class. + * + * @return the fully qualified class name of the main class, or an empty string if the main class cannot be resolved + */ + @Override + public String getValue() { + if (this.applicationMainClassName == NOT_FOUND) { + return ""; + } + return this.applicationMainClassName; + } + + private String getMainClassName(SimpleProperty property) { + String javaCommand = property.getProperty(SystemPropertyKey.SUN_JAVA_COMMAND.getKey(), "").split(" ")[0]; + if (javaCommand.isEmpty()) { + logger.log(Level.WARNING, "Error retrieving main class from " + property.getClass().getName()); + return NOT_FOUND; + } else if (javaCommand.endsWith(".jar")) { + return extractMainClassFromJar(javaCommand); + } else { + return javaCommand; + } + } + + private String extractMainClassFromJar(String jarName) { + try { + JarFile bootstrapJar = new JarFile(jarName); + return bootstrapJar.getManifest().getMainAttributes().getValue(MANIFEST_MAIN_CLASS_KEY); + } catch (Throwable t) { + logger.log(Level.WARNING, "Error retrieving main class from jar file : " + jarName, t); + return NOT_FOUND; + } + } + +} diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyCondition.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyCondition.java new file mode 100644 index 000000000..7c8abb4f6 --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyCondition.java @@ -0,0 +1,68 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.bootstrap.resolver.condition; + +import com.navercorp.pinpoint.common.util.SystemProperty; + +/** + * Checks if the specified property keys are in the system property. + * + * @author HyunGil Jeong + */ +public class SystemPropertyCondition implements Condition, ConditionValue { + + private final SystemProperty property; + + public SystemPropertyCondition() { + this(SystemProperty.INSTANCE); + } + + SystemPropertyCondition(SystemProperty property) { + this.property = property; + } + + /** + * Checks if the specified values are in the system property. + * + * @param requiredKeys the values to check if they exist in the system property + * @return true if all of the specified keys are in the system property; + * false if otherwise, or if null values are provided + */ + @Override + public boolean check(String ... requiredKeys) { + if (requiredKeys == null) { + return false; + } + for (String requiredKey : requiredKeys) { + if (this.property.getProperty(requiredKey) == null) { + return false; + } + } + return true; + } + + /** + * Returns the system property. + * + * @return the {@link SystemProperty} instance + */ + @Override + public SystemProperty getValue() { + return this.property; + } + +} diff --git a/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassConditionTest.java b/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassConditionTest.java new file mode 100644 index 000000000..3b5525ed3 --- /dev/null +++ b/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassConditionTest.java @@ -0,0 +1,147 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.bootstrap.resolver.condition; + +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import com.navercorp.pinpoint.bootstrap.resolver.condition.MainClassCondition; +import com.navercorp.pinpoint.common.util.SimpleProperty; +import com.navercorp.pinpoint.common.util.SystemPropertyKey; + +/** + * @author HyunGil Jeong + */ +public class MainClassConditionTest { + + private static final String TEST_MAIN_CLASS = "main.class.for.Test"; + + @Test + public void getValueShouldReturnBootstrapMainClass() { + // Given + SimpleProperty property = createTestProperty(TEST_MAIN_CLASS); + MainClassCondition mainClassCondition = new MainClassCondition(property); + // When + String expectedMainClass = mainClassCondition.getValue(); + // Then + assertEquals(TEST_MAIN_CLASS, expectedMainClass); + } + + @Test + public void getValueShouldReturnEmptyStringWhenMainClassCannotBeResolved() { + // Given + SimpleProperty property = createTestProperty(); + MainClassCondition mainClassCondition = new MainClassCondition(property); + // When + String expectedMainClass = mainClassCondition.getValue(); + // Then + assertEquals("", expectedMainClass); + } + + @Test + public void testMatch() { + // Given + SimpleProperty property = createTestProperty(TEST_MAIN_CLASS); + MainClassCondition mainClassCondition = new MainClassCondition(property); + // When + boolean matches = mainClassCondition.check(TEST_MAIN_CLASS); + // Then + assertTrue(matches); + } + + @Test + public void testNoMatch() { + // Given + String givenBootstrapMainClass = "some.other.main.class"; + SimpleProperty property = createTestProperty(givenBootstrapMainClass); + MainClassCondition mainClassCondition = new MainClassCondition(property); + // When + boolean matches = mainClassCondition.check(TEST_MAIN_CLASS); + // Then + assertFalse(matches); + } + + @Test + public void nullConditionShouldNotMatch() { + // Given + SimpleProperty property = createTestProperty(TEST_MAIN_CLASS); + MainClassCondition mainClassCondition = new MainClassCondition(property); + // When + boolean matches = mainClassCondition.check(null); + // Then + assertFalse(matches); + } + + @Test + public void shouldNotMatchWhenMainClassCannotBeResolved() { + // Given + SimpleProperty property = createTestProperty(); + MainClassCondition mainClassCondition = new MainClassCondition(property); + // When + boolean matches = mainClassCondition.check(null); + // Then + assertFalse(matches); + } + + @Test + public void shouldNotMatchWhenWhenJarFileCannotBeFound() { + // Given + SimpleProperty property = createTestProperty("non-existent-test-jar.jar"); + MainClassCondition mainClassCondition = new MainClassCondition(property); + // When + boolean matches = mainClassCondition.check(null); + // Then + assertFalse(matches); + } + + private static SimpleProperty createTestProperty() { + return new SimpleProperty() { + + private final Map properties = new HashMap(); + + @Override + public void setProperty(String key, String value) { + this.properties.put(key, value); + } + + @Override + public String getProperty(String key) { + return this.properties.get(key); + } + + @Override + public String getProperty(String key, String defaultValue) { + if (this.properties.containsKey(key)) { + return this.properties.get(key); + } else { + return defaultValue; + } + } + }; + } + + private static SimpleProperty createTestProperty(String testMainClass) { + SimpleProperty testProperty = createTestProperty(); + testProperty.setProperty(SystemPropertyKey.SUN_JAVA_COMMAND.getKey(), testMainClass); + return testProperty; + } + +} diff --git a/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyConditionTest.java b/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyConditionTest.java new file mode 100644 index 000000000..467491474 --- /dev/null +++ b/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyConditionTest.java @@ -0,0 +1,146 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.bootstrap.resolver.condition; + +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import com.navercorp.pinpoint.bootstrap.resolver.condition.SystemPropertyCondition; +import com.navercorp.pinpoint.common.util.SystemProperty; + +/** + * @author HyunGil Jeong + */ +public class SystemPropertyConditionTest { + + @Test + public void testMatch() { + // Given + final String existingSystemProperty1 = "set.one.key.one"; + final String existingSystemProperty2 = "set.one.key.two"; + SystemProperty property = createTestProperty(existingSystemProperty1, existingSystemProperty2); + SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); + // When + boolean matches = systemPropertyCondition.check(existingSystemProperty1, existingSystemProperty2); + // Then + assertTrue(matches); + } + + @Test + public void testNoMatch() { + // Given + final String existingSystemProperty = "existing.system.property"; + SystemProperty property = createTestProperty(existingSystemProperty); + SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); + // When + boolean matches = systemPropertyCondition.check("some.other.property"); + // Then + assertFalse(matches); + } + + @Test + public void partialMatchShouldResultInNoMatch() { + // Given + final String existingSystemProperty = "set.one.key.one"; + SystemProperty property = createTestProperty(existingSystemProperty); + SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); + // When + boolean matches = systemPropertyCondition.check(existingSystemProperty, "some.other.property"); + // Then + assertFalse(matches); + } + + @Test + public void emptyConditionShouldMatch() { + // Given + final String existingSystemProperty = "existing.system.property"; + SystemProperty property = createTestProperty(existingSystemProperty); + SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); + // When + boolean matches = systemPropertyCondition.check(new String[0]); + // Then + assertTrue(matches); + } + + @Test + public void conditionWithNullElementShouldMatch() { + // Given + final String existingSystemProperty = "existing.system.property"; + SystemProperty property = createTestProperty(existingSystemProperty); + SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); + final String[] conditionWithNullElement = new String[] {null}; + // When + boolean matches = systemPropertyCondition.check(conditionWithNullElement); + // Then + assertFalse(matches); + } + + @Test + public void nullConditionShouldNotMatch() { + // Given + final String existingSystemProperty = "existing.system.property"; + SystemProperty property = createTestProperty(existingSystemProperty); + SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); + final String[] nullCondition = null; + // When + boolean matches = systemPropertyCondition.check(nullCondition); + // Then + assertFalse(matches); + } + + private static SystemProperty createTestProperty() { + return new SystemProperty() { + + private final Map properties = new HashMap(); + + @Override + public void setProperty(String key, String value) { + this.properties.put(key, value); + } + + @Override + public String getProperty(String key) { + return this.properties.get(key); + } + + @Override + public String getProperty(String key, String defaultValue) { + if (this.properties.containsKey(key)) { + return this.properties.get(key); + } else { + return defaultValue; + } + } + }; + } + + private static SystemProperty createTestProperty(String ... keys) { + SystemProperty property = createTestProperty(); + if (keys == null) { + return property; + } + for (String key : keys) { + property.setProperty(key, ""); + } + return property; + } + +} diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/util/SystemPropertyKey.java b/commons/src/main/java/com/navercorp/pinpoint/common/util/SystemPropertyKey.java index 785b3ca84..aab8eac87 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/util/SystemPropertyKey.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/util/SystemPropertyKey.java @@ -29,7 +29,8 @@ public enum SystemPropertyKey { JAVA_VM_NAME("java.vm.name"), JAVA_VM_VERSION("java.vm.version"), JAVA_VM_INFO("java.vm.info"), - JAVA_VM_SPECIFICATION_VERSION("java.vm.specification.version"); + JAVA_VM_SPECIFICATION_VERSION("java.vm.specification.version"), + SUN_JAVA_COMMAND("sun.java.command"); // May be unsupported depending on the JVM. private final String key; diff --git a/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java b/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java index 9ff260ccb..44b9ab224 100644 --- a/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java +++ b/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java @@ -14,47 +14,34 @@ */ package com.navercorp.pinpoint.plugin.tomcat; -import java.io.File; - -import com.navercorp.pinpoint.bootstrap.logging.PLogger; -import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; import com.navercorp.pinpoint.bootstrap.plugin.ServerTypeDetector; -import com.navercorp.pinpoint.common.util.SystemProperty; +import com.navercorp.pinpoint.bootstrap.resolver.ConditionProvider; +import com.navercorp.pinpoint.common.ServiceType; /** * @author Jongho Moon + * @author HyunGil Jeong * */ public class TomcatDetector implements ServerTypeDetector, TomcatConstants { - private final PLogger logger = PLoggerFactory.getLogger(getClass()); + + private static final String REQUIRED_MAIN_CLASS = "org.apache.catalina.startup.Bootstrap"; + + private static final String REQUIRED_SYSTEM_PROPERTY = "catalina.home"; + + private static final String REQUIRED_CLASS = "org.apache.catalina.startup.Bootstrap"; @Override - public String getServerTypeName() { - return TYPE_NAME; - } - - public boolean detect() { - String homeDir = SystemProperty.INSTANCE.getProperty("catalina.home"); - - if (homeDir == null) { - logger.debug("catalina.home is not defined. This is not a Tomcat instance"); - return false; - } - - File catalinaJar = new File(homeDir, "/lib/catalina.jar"); - - if (!catalinaJar.exists()) { - logger.debug(catalinaJar + " is not exist. This is not a Tomcat instance"); - return false; - } - - logger.debug("catalina.home (" + homeDir + ") is defined and " + catalinaJar + " is exist. This is a Tomcat instance"); - - return catalinaJar.exists(); + public ServiceType getServerType() { + return TOMCAT; } @Override - public boolean canOverride(String serverType) { - return false; + public boolean detect(ConditionProvider provider) { + String bootstrapMain = provider.getMainClassCondition().getValue(); + return bootstrapMain.equals(REQUIRED_MAIN_CLASS) && + provider.getSystemPropertyCondition().check(REQUIRED_SYSTEM_PROPERTY) && + provider.getLibraryClassCondition().check(REQUIRED_CLASS); } + } diff --git a/plugins/tomcat/src/test/resources/pinpoint.config b/plugins/tomcat/src/test/resources/pinpoint.config index d8d1493fe..4fa92abdb 100644 --- a/plugins/tomcat/src/test/resources/pinpoint.config +++ b/plugins/tomcat/src/test/resources/pinpoint.config @@ -55,6 +55,10 @@ profiler.tcpdatasender.command.accept.enable=true #profiler.applicationservertype=TOMCAT #profiler.applicationservertype=BLOC +########################################################### +# application type detect order # +########################################################### +profiler.type.detect.order= ########################################################### # user defined classes # diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/DefaultAgent.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/DefaultAgent.java index 635297157..74c47a57d 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/DefaultAgent.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/DefaultAgent.java @@ -43,7 +43,6 @@ import com.navercorp.pinpoint.common.ServiceType; import com.navercorp.pinpoint.common.plugin.PluginLoader; import com.navercorp.pinpoint.common.service.DefaultServiceTypeRegistryService; import com.navercorp.pinpoint.common.service.ServiceTypeRegistryService; -import com.navercorp.pinpoint.exception.PinpointException; import com.navercorp.pinpoint.profiler.context.DefaultServerMetaDataHolder; import com.navercorp.pinpoint.profiler.context.DefaultTraceContext; import com.navercorp.pinpoint.profiler.context.storage.BufferedStorageFactory; @@ -170,15 +169,12 @@ public class DefaultAgent implements Agent { String applicationServerTypeString = profilerConfig.getApplicationServerType(); ServiceType applicationServerType = this.serviceTypeRegistryService.findServiceTypeByName(applicationServerTypeString); - final ApplicationServerTypeResolver typeResolver = new ApplicationServerTypeResolver(pluginContexts, applicationServerType, this.serviceTypeRegistryService); - if (!typeResolver.resolve()) { - throw new PinpointException("ApplicationServerType not found."); - } + final ApplicationServerTypeResolver typeResolver = new ApplicationServerTypeResolver(pluginContexts, applicationServerType, profilerConfig.getApplicationTypeDetectOrder()); final AgentInformationFactory agentInformationFactory = new AgentInformationFactory(); - this.agentInformation = agentInformationFactory.createAgentInformation(typeResolver.getServerType()); + this.agentInformation = agentInformationFactory.createAgentInformation(typeResolver.resolve()); logger.info("agentInformation:{}", agentInformation); - + CommandDispatcher commandDispatcher = createCommandDispatcher(); this.tcpDataSender = createTcpDataSender(commandDispatcher); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java index 6230c4763..7e662b0d4 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java @@ -17,85 +17,72 @@ package com.navercorp.pinpoint.profiler.util; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.navercorp.pinpoint.bootstrap.plugin.ServerTypeDetector; +import com.navercorp.pinpoint.bootstrap.resolver.ApplicationServerTypePluginResolver; import com.navercorp.pinpoint.common.ServiceType; -import com.navercorp.pinpoint.common.service.ServiceTypeRegistryService; import com.navercorp.pinpoint.profiler.plugin.DefaultProfilerPluginContext; /** * @author emeroad * @author netspider + * @author hyungil.jeong */ public class ApplicationServerTypeResolver { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); - private ServiceType serverType; - private final ServiceType defaultType; + private final ApplicationServerTypePluginResolver resolver; private final List detectors = new ArrayList(); - private final ServiceTypeRegistryService serviceTypeRegistryService; - - public ApplicationServerTypeResolver(List plugins, ServiceType defaultType, ServiceTypeRegistryService serviceTypeRegistryService) { - if (serviceTypeRegistryService == null) { - throw new NullPointerException("serviceTypeRegistryService must not be null"); + public ApplicationServerTypeResolver(List plugins, ServiceType defaultType, List orderedDetectors) { + if (isValidApplicationServerType(defaultType)) { + this.defaultType = defaultType; + } else { + this.defaultType = ServiceType.UNDEFINED; } - this.serviceTypeRegistryService = serviceTypeRegistryService; - this.defaultType = defaultType; - - for (DefaultProfilerPluginContext context : plugins) { - detectors.addAll(context.getServerTypeDetectors()); + Map registeredDetectors = getRegisteredServerTypeDetectors(plugins); + for (String orderedDetector : orderedDetectors) { + if (registeredDetectors.containsKey(orderedDetector)); + this.detectors.add(registeredDetectors.remove(orderedDetector)); } - } - - public String[] getServerLibPath() { - return new String[0]; - } - - public ServiceType getServerType() { - return serverType; + this.detectors.addAll(registeredDetectors.values()); + this.resolver = new ApplicationServerTypePluginResolver(this.detectors); } - public boolean resolve() { - String serverType = null; - - for (ServerTypeDetector detector : detectors) { - logger.debug("try to resolve using {}", detector.getClass()); - - if (serverType != null && !detector.canOverride(serverType)) { - continue; - } - - if (detector.detect()) { - serverType = detector.getServerTypeName(); - - if (logger.isInfoEnabled()) { - logger.info("Resolved applicationServerType [{}] by {}", serverType, detector.getClass().getName()); - } + private Map getRegisteredServerTypeDetectors(List plugins) { + Map registeredDetectors = new HashMap(); + for (DefaultProfilerPluginContext context : plugins) { + for (ServerTypeDetector detector : context.getServerTypeDetectors()) { + registeredDetectors.put(detector.getClass().getName(), detector); } } - - if (serverType != null) { - this.serverType = serviceTypeRegistryService.findServiceTypeByName(serverType); - return true; - } - - if (defaultType != null) { - // TODO validate default type. is defaultType a server type? - this.serverType = defaultType; + return registeredDetectors; + } + + public ServiceType resolve() { + ServiceType resolvedApplicationServerType; + if (this.defaultType == ServiceType.UNDEFINED) { + resolvedApplicationServerType = this.resolver.resolve(); + logger.info("Resolved ApplicationServerType : {}", resolvedApplicationServerType.getName()); } else { - this.serverType = ServiceType.STAND_ALONE; + resolvedApplicationServerType = this.defaultType; + logger.info("Configured ApplicationServerType : {}", resolvedApplicationServerType.getName()); } - - if (logger.isInfoEnabled()) { - logger.info("Configured applicationServerType:{}", defaultType); + return resolvedApplicationServerType; + } + + private boolean isValidApplicationServerType(ServiceType serviceType) { + if (serviceType == null) { + return false; } - - return true; + return serviceType.isWas(); } } diff --git a/profiler/src/test/resources/pinpoint-spring-bean-test.config b/profiler/src/test/resources/pinpoint-spring-bean-test.config index 3c787b397..5a376f9a4 100644 --- a/profiler/src/test/resources/pinpoint-spring-bean-test.config +++ b/profiler/src/test/resources/pinpoint-spring-bean-test.config @@ -1,197 +1,201 @@ -# -# Pinpoint agent configuration -# - -########################################################### -# Collector server # -########################################################### -profiler.collector.ip=127.0.0.1 - -# placeHolder support "${key}" -profiler.collector.span.ip=${profiler.collector.ip} -profiler.collector.span.port=9996 - -# placeHolder support "${key}" -profiler.collector.stat.ip=${profiler.collector.ip} -profiler.collector.stat.port=9995 - -# placeHolder support "${key}" -profiler.collector.tcp.ip=${profiler.collector.ip} -profiler.collector.tcp.port=9994 - - -########################################################### -# Profiler Global Configuration # -########################################################### -profiler.enable=true - -profiler.jvm.collect.interval=1000 - -profiler.sampling.enable=true - -# Set sampling rate. If you set it to 10, 1 out of 10 transaction will be sampled. -profiler.sampling.rate=1 - -profiler.io.buffering.enable=true -profiler.io.buffering.buffersize=20 - -profiler.spandatasender.write.queue.size=5120 -#profiler.spandatasender.socket.sendbuffersize=1048576 -#profiler.spandatasender.socket.timeout=3000 -profiler.spandatasender.chunk.size=16384 - -profiler.statdatasender.write.queue.size=5120 -#profiler.statdatasender.socket.sendbuffersize=1048576 -#profiler.statdatasender.socket.timeout=3000 -profiler.statdatasender.chunk.size=16384 - -profiler.agentInfo.send.retry.interval=300000 - -# Allows TCP data command -profiler.tcpdatasender.command.accept.enable=true - -########################################################### -# application type # -########################################################### -#profiler.applicationservertype=TOMCAT -#profiler.applicationservertype=BLOC - - -########################################################### -# user defined classes # -########################################################### -profiler.include= - -########################################################### -# TOMCAT # -########################################################### -profiler.tomcat.hidepinpointheader=true -profiler.tomcat.excludeurl=/aa/test.html, /bb/exclude.html - -########################################################### -# JDBC # -########################################################### -profiler.jdbc=true -profiler.jdbc.sqlcachesize=1024 -profiler.jdbc.maxsqlbindvaluesize=1024 - -# -# MYSQL -# -profiler.jdbc.mysql=true -profiler.jdbc.mysql.setautocommit=true -profiler.jdbc.mysql.commit=true -profiler.jdbc.mysql.rollback=true - -# -# MSSQL Jtds -# -profiler.jdbc.jtds=true -profiler.jdbc.jtds.setautocommit=true -profiler.jdbc.jtds.commit=true -profiler.jdbc.jtds.rollback=true - -# -# Oracle -# -profiler.jdbc.oracle=true -profiler.jdbc.oracle.setautocommit=true -profiler.jdbc.oracle.commit=true -profiler.jdbc.oracle.rollback=true - -# -# CUBRID -# -profiler.jdbc.cubrid=true -profiler.jdbc.cubrid.setautocommit=true -profiler.jdbc.cubrid.commit=true -profiler.jdbc.cubrid.rollback=true - -# -# DBCP -# -profiler.jdbc.dbcp=true -profiler.jdbc.dbcp.connectionclose=true - - -########################################################### -# Apache HTTP Client 4.x # -########################################################### -profiler.apache.httpclient4=true -profiler.apache.httpclient4.cookie=true - -# When cookies should be dumped. It could be ALWAYS or EXCEPTION. -profiler.apache.httpclient4.cookie.dumptype=ALWAYS -profiler.apache.httpclient4.cookie.sampling.rate=1 - -# Dump entities of POST or PUT request. limited to entities which is HttpEtity.isRepeatable() == true. -profiler.apache.httpclient4.entity=true - -# When entities should be dumped. ALWAYS or EXCEPTION. -profiler.apache.httpclient4.entity.dumptype=ALWAYS -profiler.apache.httpclient4.entity.sampling.rate=1 - -profiler.apache.nio.httpclient4=true - - -########################################################### -# Ning Async HTTP Client # -########################################################### -profiler.ning.asynchttpclient=true -profiler.ning.asynchttpclient.cookie=true -profiler.ning.asynchttpclient.cookie.dumptype=ALWAYS -profiler.ning.asynchttpclient.cookie.dumpsize=1024 -profiler.ning.asynchttpclient.cookie.sampling.rate=1 -profiler.ning.asynchttpclient.entity=true -profiler.ning.asynchttpclient.entity.dumptype=ALWAYS -profiler.ning.asynchttpclient.entity.dumpsize=1024 -profiler.ning.asynchttpclient.entity.sampling.rate=1 -profiler.ning.asynchttpclient.param=true -profiler.ning.asynchttpclient.param.dumptype=ALWAYS -profiler.ning.asynchttpclient.param.dumpsize=1024 -profiler.ning.asynchttpclient.param.sampling.rate=1 - - -########################################################### -# Arcus # -########################################################### -profiler.arcus=true -profiler.arcus.keytrace=true - - -########################################################### -# Memcached # -########################################################### -profiler.memcached=true -profiler.memcached.keytrace=true - - -########################################################### -# ibatis # -########################################################### -profiler.orm.ibatis=true - - -########################################################### -# mybatis # -########################################################### -profiler.orm.mybatis=true - - -########################################################### -# spring-beans -########################################################### -profiler.spring.beans=true -profiler.spring.beans.name.pattern=ma.*, outer -profiler.spring.beans.class.pattern=.*Morae -profiler.spring.beans.annotation=org.springframework.stereotype.Component - -########################################################### -# log4j -########################################################### -profiler.log4j.logging.transactioninfo=false - -########################################################### -# logback -########################################################### -profiler.logback.logging.transactioninfo=false \ No newline at end of file +# +# Pinpoint agent configuration +# + +########################################################### +# Collector server # +########################################################### +profiler.collector.ip=127.0.0.1 + +# placeHolder support "${key}" +profiler.collector.span.ip=${profiler.collector.ip} +profiler.collector.span.port=9996 + +# placeHolder support "${key}" +profiler.collector.stat.ip=${profiler.collector.ip} +profiler.collector.stat.port=9995 + +# placeHolder support "${key}" +profiler.collector.tcp.ip=${profiler.collector.ip} +profiler.collector.tcp.port=9994 + + +########################################################### +# Profiler Global Configuration # +########################################################### +profiler.enable=true + +profiler.jvm.collect.interval=1000 + +profiler.sampling.enable=true + +# Set sampling rate. If you set it to 10, 1 out of 10 transaction will be sampled. +profiler.sampling.rate=1 + +profiler.io.buffering.enable=true +profiler.io.buffering.buffersize=20 + +profiler.spandatasender.write.queue.size=5120 +#profiler.spandatasender.socket.sendbuffersize=1048576 +#profiler.spandatasender.socket.timeout=3000 +profiler.spandatasender.chunk.size=16384 + +profiler.statdatasender.write.queue.size=5120 +#profiler.statdatasender.socket.sendbuffersize=1048576 +#profiler.statdatasender.socket.timeout=3000 +profiler.statdatasender.chunk.size=16384 + +profiler.agentInfo.send.retry.interval=300000 + +# Allows TCP data command +profiler.tcpdatasender.command.accept.enable=true + +########################################################### +# application type # +########################################################### +#profiler.applicationservertype=TOMCAT +#profiler.applicationservertype=BLOC + +########################################################### +# application type detect order # +########################################################### +profiler.type.detect.order= + +########################################################### +# user defined classes # +########################################################### +profiler.include= + +########################################################### +# TOMCAT # +########################################################### +profiler.tomcat.hidepinpointheader=true +profiler.tomcat.excludeurl=/aa/test.html, /bb/exclude.html + +########################################################### +# JDBC # +########################################################### +profiler.jdbc=true +profiler.jdbc.sqlcachesize=1024 +profiler.jdbc.maxsqlbindvaluesize=1024 + +# +# MYSQL +# +profiler.jdbc.mysql=true +profiler.jdbc.mysql.setautocommit=true +profiler.jdbc.mysql.commit=true +profiler.jdbc.mysql.rollback=true + +# +# MSSQL Jtds +# +profiler.jdbc.jtds=true +profiler.jdbc.jtds.setautocommit=true +profiler.jdbc.jtds.commit=true +profiler.jdbc.jtds.rollback=true + +# +# Oracle +# +profiler.jdbc.oracle=true +profiler.jdbc.oracle.setautocommit=true +profiler.jdbc.oracle.commit=true +profiler.jdbc.oracle.rollback=true + +# +# CUBRID +# +profiler.jdbc.cubrid=true +profiler.jdbc.cubrid.setautocommit=true +profiler.jdbc.cubrid.commit=true +profiler.jdbc.cubrid.rollback=true + +# +# DBCP +# +profiler.jdbc.dbcp=true +profiler.jdbc.dbcp.connectionclose=true + + +########################################################### +# Apache HTTP Client 4.x # +########################################################### +profiler.apache.httpclient4=true +profiler.apache.httpclient4.cookie=true + +# When cookies should be dumped. It could be ALWAYS or EXCEPTION. +profiler.apache.httpclient4.cookie.dumptype=ALWAYS +profiler.apache.httpclient4.cookie.sampling.rate=1 + +# Dump entities of POST or PUT request. limited to entities which is HttpEtity.isRepeatable() == true. +profiler.apache.httpclient4.entity=true + +# When entities should be dumped. ALWAYS or EXCEPTION. +profiler.apache.httpclient4.entity.dumptype=ALWAYS +profiler.apache.httpclient4.entity.sampling.rate=1 + +profiler.apache.nio.httpclient4=true + + +########################################################### +# Ning Async HTTP Client # +########################################################### +profiler.ning.asynchttpclient=true +profiler.ning.asynchttpclient.cookie=true +profiler.ning.asynchttpclient.cookie.dumptype=ALWAYS +profiler.ning.asynchttpclient.cookie.dumpsize=1024 +profiler.ning.asynchttpclient.cookie.sampling.rate=1 +profiler.ning.asynchttpclient.entity=true +profiler.ning.asynchttpclient.entity.dumptype=ALWAYS +profiler.ning.asynchttpclient.entity.dumpsize=1024 +profiler.ning.asynchttpclient.entity.sampling.rate=1 +profiler.ning.asynchttpclient.param=true +profiler.ning.asynchttpclient.param.dumptype=ALWAYS +profiler.ning.asynchttpclient.param.dumpsize=1024 +profiler.ning.asynchttpclient.param.sampling.rate=1 + + +########################################################### +# Arcus # +########################################################### +profiler.arcus=true +profiler.arcus.keytrace=true + + +########################################################### +# Memcached # +########################################################### +profiler.memcached=true +profiler.memcached.keytrace=true + + +########################################################### +# ibatis # +########################################################### +profiler.orm.ibatis=true + + +########################################################### +# mybatis # +########################################################### +profiler.orm.mybatis=true + + +########################################################### +# spring-beans +########################################################### +profiler.spring.beans=true +profiler.spring.beans.name.pattern=ma.*, outer +profiler.spring.beans.class.pattern=.*Morae +profiler.spring.beans.annotation=org.springframework.stereotype.Component + +########################################################### +# log4j +########################################################### +profiler.log4j.logging.transactioninfo=false + +########################################################### +# logback +########################################################### +profiler.logback.logging.transactioninfo=false diff --git a/profiler/src/test/resources/pinpoint.config b/profiler/src/test/resources/pinpoint.config index 407712f5e..7494b10d8 100644 --- a/profiler/src/test/resources/pinpoint.config +++ b/profiler/src/test/resources/pinpoint.config @@ -55,6 +55,10 @@ profiler.tcpdatasender.command.accept.enable=true #profiler.applicationservertype=TOMCAT #profiler.applicationservertype=BLOC +########################################################### +# application type detect order # +########################################################### +profiler.type.detect.order= ########################################################### # user defined classes # @@ -206,4 +210,4 @@ profiler.log4j.logging.transactioninfo=false ########################################################### # logback ########################################################### -profiler.logback.logging.transactioninfo=false \ No newline at end of file +profiler.logback.logging.transactioninfo=false From 7d1941347a594ecc3faa4fa8b1d244c080a186f7 Mon Sep 17 00:00:00 2001 From: HyunGil Jeong Date: Fri, 20 Mar 2015 14:42:56 +0900 Subject: [PATCH 5/9] [#195] simplified API for ConditionProvider --- .../bootstrap/resolver/ConditionProvider.java | 105 ++++++---- ...ition.java => ClassResourceCondition.java} | 24 +-- .../condition/MainClassCondition.java | 8 +- ...yCondition.java => PropertyCondition.java} | 39 ++-- .../resolver/ConditionProviderTest.java | 196 ++++++++++++++++++ .../SystemPropertyConditionTest.java | 52 ++--- .../plugin/tomcat/TomcatDetector.java | 7 +- 7 files changed, 304 insertions(+), 127 deletions(-) rename bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/{LibraryClassCondition.java => ClassResourceCondition.java} (56%) rename bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/{SystemPropertyCondition.java => PropertyCondition.java} (50%) create mode 100644 bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProviderTest.java diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProvider.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProvider.java index 050d72e1c..b493c8419 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProvider.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProvider.java @@ -16,69 +16,90 @@ package com.navercorp.pinpoint.bootstrap.resolver; -import java.util.HashMap; -import java.util.Map; - -import com.navercorp.pinpoint.bootstrap.resolver.condition.Condition; -import com.navercorp.pinpoint.bootstrap.resolver.condition.LibraryClassCondition; +import com.navercorp.pinpoint.bootstrap.resolver.condition.ClassResourceCondition; import com.navercorp.pinpoint.bootstrap.resolver.condition.MainClassCondition; -import com.navercorp.pinpoint.bootstrap.resolver.condition.SystemPropertyCondition; +import com.navercorp.pinpoint.bootstrap.resolver.condition.PropertyCondition; /** + * * @author HyunGil Jeong */ public class ConditionProvider { - + public static final ConditionProvider DEFAULT_CONDITION_PROVIDER = new ConditionProvider(); - - private final Map>, Condition> conditions; - - public ConditionProvider() { - this(new HashMap>, Condition>()); + + private final MainClassCondition mainClassCondition; + + private final PropertyCondition systemPropertyCondition; + + private final ClassResourceCondition classResourceCondition; + + private ConditionProvider() { + this(new MainClassCondition(), new PropertyCondition(), new ClassResourceCondition()); } - - public ConditionProvider(Map>, Condition> conditions) { - this.conditions = conditions; - addDefaultConditions(); + + ConditionProvider(MainClassCondition mainClassCondition, PropertyCondition systemPropertyCondition, ClassResourceCondition classResourceCondition) { + this.mainClassCondition = mainClassCondition; + this.systemPropertyCondition = systemPropertyCondition; + this.classResourceCondition = classResourceCondition; } - - private void addDefaultConditions() { - this.conditions.put(MainClassCondition.class, new MainClassCondition()); - this.conditions.put(SystemPropertyCondition.class, new SystemPropertyCondition()); - this.conditions.put(LibraryClassCondition.class, new LibraryClassCondition()); - } - - public > T getCondition(Class conditionClass) { - @SuppressWarnings("unchecked") - T condition = (T)this.conditions.get(conditionClass); - return condition; + + /** + * Returns the fully qualified class name of the application's main class. + * + * @return the fully qualified class name of the main class, or an empty string if the main class cannot be resolved + * @see MainClassCondition#getValue() + */ + public String getMainClass() { + return this.mainClassCondition.getValue(); } /** - * Returns {@link MainClassCondition} that allows plugins to check for the application's bootstrap main class. + * Checks if the specified value matches the fully qualified class name of the application's main class. + * If the main class cannot be resolved, the method return false. * - * @return the {@link MainClassCondition} + * @param condition the value to check against the application's main class name + * @return true if the specified value matches the name of the main class; + * false if otherwise, or if the main class cannot be resolved + * @see MainClassCondition#check(String) */ - public MainClassCondition getMainClassCondition() { - return (MainClassCondition)this.conditions.get(MainClassCondition.class); + public boolean checkMainClass(String mainClass) { + return this.mainClassCondition.check(mainClass); } - + /** - * Returns {@link SystemPropertyCondition} that allows plugins to check for system property keys. + * Returns the system property value for the specified key. * - * @return the {@link SystemPropertyCondition} + * @return the system property value, or an empty string if the key is null or empty */ - public SystemPropertyCondition getSystemPropertyCondition() { - return (SystemPropertyCondition)this.conditions.get(SystemPropertyCondition.class); + public String getSystemPropertyValue(String systemPropertyKey) { + if (systemPropertyKey == null || systemPropertyKey.isEmpty()) { + return ""; + } + return this.systemPropertyCondition.getValue().getProperty(systemPropertyKey); } - + /** - * Returns {@link LibraryClassCondition} that allows plugins to check for classes accessible by - * the system class loader. + * Checks if the specified value is in the system property. * - * @return the {@link LibraryClassCondition} + * @param requiredKey the values to check if they exist in the system property + * @return true if the specified key is in the system property; + * false if otherwise, or if null or empty key is provided */ - public LibraryClassCondition getLibraryClassCondition() { - return (LibraryClassCondition)this.conditions.get(LibraryClassCondition.class); + public boolean checkSystemProperty(String systemPropertyKey) { + return this.systemPropertyCondition.check(systemPropertyKey); } + + /** + * Checks if the specified class can be found in the current System ClassLoader's search path. + * + * @param requiredClass the fully qualified class name of the class to check + * @return true if the specified class can be found in the system class loader's search path, + * false if otherwise + * @see ClassResourceCondition#check(String) + */ + public boolean checkForClass(String requiredClass) { + return this.classResourceCondition.check(requiredClass); + } + } diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/LibraryClassCondition.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/ClassResourceCondition.java similarity index 56% rename from bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/LibraryClassCondition.java rename to bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/ClassResourceCondition.java index 19883464a..89c9ba570 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/LibraryClassCondition.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/ClassResourceCondition.java @@ -17,11 +17,10 @@ package com.navercorp.pinpoint.bootstrap.resolver.condition; /** - * Checks whether the specified classes are currently accessible by the System ClassLoader. - * * @author HyunGil Jeong + * */ -public class LibraryClassCondition implements Condition { +public class ClassResourceCondition implements Condition { private static final String CLASS_EXTENSION = ".class"; @@ -31,24 +30,19 @@ public class LibraryClassCondition implements Condition { } /** - * Checks if the specified classes can be found in the current System ClassLoader's search path. + * Checks if the specified class can be found in the current System ClassLoader's search path. * - * @param requiredClasses the fully qualified class names of the classes to check - * @return true if all of the specified classes can be found in the system class loader's search path, + * @param requiredClass the fully qualified class name of the class to check + * @return true if the specified class can be found in the system class loader's search path, * false if otherwise */ @Override - public boolean check(String ... requiredClasses) { - if (requiredClasses == null) { + public boolean check(String requiredClass) { + if (requiredClass == null || requiredClass.isEmpty()) { return false; } - for (String condition : requiredClasses) { - String classNameAsResource = getClassNameAsResource(condition); - if (ClassLoader.getSystemResource(classNameAsResource) == null) { - return false; - } - } - return true; + String classNameAsResource = getClassNameAsResource(requiredClass); + return (ClassLoader.getSystemResource(classNameAsResource) != null); } } diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassCondition.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassCondition.java index 86ae5b895..3d21d5390 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassCondition.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/condition/MainClassCondition.java @@ -25,12 +25,8 @@ import com.navercorp.pinpoint.common.util.SystemProperty; import com.navercorp.pinpoint.common.util.SystemPropertyKey; /** - * Checks if the application's main class is in one of those specified in {@link MainClassCondition}. - *

- * The application's main class is extracted by reading the sun.java.command system property, and in cases - * of executable jars, the Main-Class attribute inside the manifest file. - * * @author HyunGil Jeong + * */ public class MainClassCondition implements Condition, ConditionValue { @@ -45,7 +41,7 @@ public class MainClassCondition implements Condition, ConditionValue, ConditionValue { +public class PropertyCondition implements Condition, ConditionValue { - private final SystemProperty property; - - public SystemPropertyCondition() { + private final SimpleProperty property; + + public PropertyCondition() { this(SystemProperty.INSTANCE); } - SystemPropertyCondition(SystemProperty property) { + public PropertyCondition(SimpleProperty property) { this.property = property; } /** - * Checks if the specified values are in the system property. + * Checks if the specified value is in SimpleProperty. * - * @param requiredKeys the values to check if they exist in the system property - * @return true if all of the specified keys are in the system property; - * false if otherwise, or if null values are provided + * @param requiredKey the values to check if they exist in SimpleProperty + * @return true if the specified key is in SimpleProperty; + * false if otherwise, or if null or empty key is provided */ @Override - public boolean check(String ... requiredKeys) { - if (requiredKeys == null) { + public boolean check(String requiredKey) { + if (requiredKey == null || requiredKey.isEmpty()) { return false; } - for (String requiredKey : requiredKeys) { - if (this.property.getProperty(requiredKey) == null) { - return false; - } - } - return true; + return (this.property.getProperty(requiredKey) != null); } /** - * Returns the system property. + * Returns the SimpleProperty. * - * @return the {@link SystemProperty} instance + * @return the {@link SimpleProperty} instance */ @Override - public SystemProperty getValue() { + public SimpleProperty getValue() { return this.property; } diff --git a/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProviderTest.java b/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProviderTest.java new file mode 100644 index 000000000..e12a9e6f1 --- /dev/null +++ b/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/ConditionProviderTest.java @@ -0,0 +1,196 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.bootstrap.resolver; + +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +import com.navercorp.pinpoint.bootstrap.resolver.condition.ClassResourceCondition; +import com.navercorp.pinpoint.bootstrap.resolver.condition.MainClassCondition; +import com.navercorp.pinpoint.bootstrap.resolver.condition.PropertyCondition; +import com.navercorp.pinpoint.common.util.SimpleProperty; +import com.navercorp.pinpoint.common.util.SystemPropertyKey; + +/** + * @author HyunGil Jeong + */ +public class ConditionProviderTest { + + private static final String TEST_MAIN_CLASS = "test.main.class"; + private static final String TEST_PROPERTY_KEY = "test.property.key"; + private static final String TEST_PROPERTY_VALUE = "test.property.value"; + + private ConditionProvider conditionProvider; + + @Before + public void setUp() throws Exception { + this.conditionProvider = new ConditionProvider( + new MainClassCondition(PROPERTY_FOR_TEST), + new PropertyCondition(PROPERTY_FOR_TEST), + new ClassResourceCondition() + ); + } + + @Test + public void getMainClassShouldReturnApplicationMainClass() { + // Given + final String expectedMainClass = TEST_MAIN_CLASS; + // When + String actualMainClass = this.conditionProvider.getMainClass(); + // Then + assertEquals(expectedMainClass, actualMainClass); + } + + @Test + public void checkMainClassShouldReturnTrueForMatchingMainClasses() { + // Given + final String matchingMainClass = TEST_MAIN_CLASS; + // When + boolean matches = this.conditionProvider.checkMainClass(matchingMainClass); + // Then + assertTrue(matches); + } + + @Test + public void checkMainClassShouldReturnFalseForNonMatchingMainClasses() { + // Given + final String someOtherMainClass = "some.other.main.class"; + // When + boolean matches = this.conditionProvider.checkMainClass(someOtherMainClass); + // Then + assertFalse(matches); + } + + @Test + public void checkMainClassShouldReturnForNullParameter() { + // Given + // When + boolean matches = this.conditionProvider.checkMainClass(null); + // Then + assertFalse(matches); + } + + @Test + public void checkMainClassShouldReturnForEmptyParameter() { + // Given + // When + boolean matches = this.conditionProvider.checkMainClass(""); + // Then + assertFalse(matches); + } + + @Test + public void getSystemPropertyValueShouldReturnCorrectValue() { + // Given + final String expectedValue = TEST_PROPERTY_VALUE; + // When + String actualValue = this.conditionProvider.getSystemPropertyValue(TEST_PROPERTY_KEY); + // Then + assertEquals(expectedValue, actualValue); + } + + @Test + public void getSystemPropertyValueShouldReturnEmptyStringForNullKey() { + // Given + final String expectedValue = ""; + // When + String actualValue = this.conditionProvider.getSystemPropertyValue(null); + // Then + assertEquals(expectedValue, actualValue); + } + + @Test + public void getSystemPropertyValueShouldReturnEmptyStringForEmptyKey() { + // Given + final String expectedValue = ""; + // When + String actualValue = this.conditionProvider.getSystemPropertyValue(""); + // Then + assertEquals(expectedValue, actualValue); + } + + @Test + public void checkSystemPropertyShouldReturnTrueForExistingKeys() { + // Given + // When + boolean exists = this.conditionProvider.checkSystemProperty(TEST_PROPERTY_KEY); + // Then + assertTrue(exists); + } + + @Test + public void checkSystemPropertyShouldReturnFalseForNonExistingKeys() { + // Given + final String nonExistingKey = "some.other.property.key"; + // When + boolean exists = this.conditionProvider.checkSystemProperty(nonExistingKey); + // Then + assertFalse(exists); + } + + @Test + public void checkSystemPropertyShouldReturnFalseForNullKeys() { + // Given + // When + boolean exists = this.conditionProvider.checkSystemProperty(null); + // Then + assertFalse(exists); + } + + @Test + public void checkSystemPropertyShouldReturnFalseForEmptyKeys() { + // Given + // When + boolean exists = this.conditionProvider.checkSystemProperty(""); + // Then + assertFalse(exists); + } + + private static final SimpleProperty PROPERTY_FOR_TEST = new SimpleProperty() { + + @SuppressWarnings("serial") + private final Map properties = new HashMap() {{ + put(SystemPropertyKey.SUN_JAVA_COMMAND.getKey(), TEST_MAIN_CLASS); + put(TEST_PROPERTY_KEY, TEST_PROPERTY_VALUE); + }}; + + @Override + public void setProperty(String key, String value) { + this.properties.put(key, value); + } + + @Override + public String getProperty(String key) { + return this.properties.get(key); + } + + @Override + public String getProperty(String key, String defaultValue) { + if (this.properties.containsKey(key)) { + return this.properties.get(key); + } + return defaultValue; + } + + }; + +} diff --git a/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyConditionTest.java b/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyConditionTest.java index 467491474..09eb25e2c 100644 --- a/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyConditionTest.java +++ b/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/resolver/condition/SystemPropertyConditionTest.java @@ -23,7 +23,7 @@ import java.util.Map; import org.junit.Test; -import com.navercorp.pinpoint.bootstrap.resolver.condition.SystemPropertyCondition; +import com.navercorp.pinpoint.bootstrap.resolver.condition.PropertyCondition; import com.navercorp.pinpoint.common.util.SystemProperty; /** @@ -37,11 +37,13 @@ public class SystemPropertyConditionTest { final String existingSystemProperty1 = "set.one.key.one"; final String existingSystemProperty2 = "set.one.key.two"; SystemProperty property = createTestProperty(existingSystemProperty1, existingSystemProperty2); - SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); + PropertyCondition systemPropertyCondition = new PropertyCondition(property); // When - boolean matches = systemPropertyCondition.check(existingSystemProperty1, existingSystemProperty2); + boolean firstKeyExists = systemPropertyCondition.check(existingSystemProperty1); + boolean secondKeyExists = systemPropertyCondition.check(existingSystemProperty2); // Then - assertTrue(matches); + assertTrue(firstKeyExists); + assertTrue(secondKeyExists); } @Test @@ -49,46 +51,21 @@ public class SystemPropertyConditionTest { // Given final String existingSystemProperty = "existing.system.property"; SystemProperty property = createTestProperty(existingSystemProperty); - SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); + PropertyCondition systemPropertyCondition = new PropertyCondition(property); // When - boolean matches = systemPropertyCondition.check("some.other.property"); + boolean keyExists = systemPropertyCondition.check("some.other.property"); // Then - assertFalse(matches); + assertFalse(keyExists); } @Test - public void partialMatchShouldResultInNoMatch() { - // Given - final String existingSystemProperty = "set.one.key.one"; - SystemProperty property = createTestProperty(existingSystemProperty); - SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); - // When - boolean matches = systemPropertyCondition.check(existingSystemProperty, "some.other.property"); - // Then - assertFalse(matches); - } - - @Test - public void emptyConditionShouldMatch() { + public void emptyConditionShouldNotMatch() { // Given final String existingSystemProperty = "existing.system.property"; SystemProperty property = createTestProperty(existingSystemProperty); - SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); + PropertyCondition systemPropertyCondition = new PropertyCondition(property); // When - boolean matches = systemPropertyCondition.check(new String[0]); - // Then - assertTrue(matches); - } - - @Test - public void conditionWithNullElementShouldMatch() { - // Given - final String existingSystemProperty = "existing.system.property"; - SystemProperty property = createTestProperty(existingSystemProperty); - SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); - final String[] conditionWithNullElement = new String[] {null}; - // When - boolean matches = systemPropertyCondition.check(conditionWithNullElement); + boolean matches = systemPropertyCondition.check(""); // Then assertFalse(matches); } @@ -98,10 +75,9 @@ public class SystemPropertyConditionTest { // Given final String existingSystemProperty = "existing.system.property"; SystemProperty property = createTestProperty(existingSystemProperty); - SystemPropertyCondition systemPropertyCondition = new SystemPropertyCondition(property); - final String[] nullCondition = null; + PropertyCondition systemPropertyCondition = new PropertyCondition(property); // When - boolean matches = systemPropertyCondition.check(nullCondition); + boolean matches = systemPropertyCondition.check(null); // Then assertFalse(matches); } diff --git a/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java b/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java index 44b9ab224..5c26f8dd2 100644 --- a/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java +++ b/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java @@ -38,10 +38,9 @@ public class TomcatDetector implements ServerTypeDetector, TomcatConstants { @Override public boolean detect(ConditionProvider provider) { - String bootstrapMain = provider.getMainClassCondition().getValue(); - return bootstrapMain.equals(REQUIRED_MAIN_CLASS) && - provider.getSystemPropertyCondition().check(REQUIRED_SYSTEM_PROPERTY) && - provider.getLibraryClassCondition().check(REQUIRED_CLASS); + return provider.checkMainClass(REQUIRED_MAIN_CLASS) && + provider.checkSystemProperty(REQUIRED_SYSTEM_PROPERTY) && + provider.checkForClass(REQUIRED_CLASS); } } From df4a3f948b8b9a27db82f367209cc1389e827885 Mon Sep 17 00:00:00 2001 From: HyunGil Jeong Date: Mon, 23 Mar 2015 14:44:02 +0900 Subject: [PATCH 6/9] fixed a bug regarding missing conditional check. --- .../profiler/util/ApplicationServerTypeResolver.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java index 7e662b0d4..6bc11379d 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java @@ -50,8 +50,9 @@ public class ApplicationServerTypeResolver { } Map registeredDetectors = getRegisteredServerTypeDetectors(plugins); for (String orderedDetector : orderedDetectors) { - if (registeredDetectors.containsKey(orderedDetector)); - this.detectors.add(registeredDetectors.remove(orderedDetector)); + if (registeredDetectors.containsKey(orderedDetector)) { + this.detectors.add(registeredDetectors.remove(orderedDetector)); + } } this.detectors.addAll(registeredDetectors.values()); this.resolver = new ApplicationServerTypePluginResolver(this.detectors); From d75cd02d2267490bdeb2ecdad55f2754e4025f43 Mon Sep 17 00:00:00 2001 From: Jongho Moon Date: Wed, 18 Mar 2015 14:25:04 +0900 Subject: [PATCH 7/9] [#235] intercept not only connect() but also getInputStream() and getOUtputStream() - ConnectMethodInterceptor will check 'connected' before setting request headers. --- .../jdkhttpconnector/HttpURLConnectionIT.java | 51 +++++++++++++++++++ .../bootstrap/instrument/InstrumentClass.java | 2 + .../interceptor/bci/JavaAssistClass.java | 13 ++++- .../HttpURLConnectionModifier.java | 24 +++++++-- .../interceptor/ConnectMethodInterceptor.java | 28 ++++++---- .../test/plugin/DependencyResolver.java | 12 ++--- .../test/plugin/ForkedPinpointPluginTest.java | 1 - .../ForkedPinpointPluginTestRunner.java | 7 ++- .../plugin/PinpointPluginTestConstants.java | 1 - ....java => PinpointPluginTestException.java} | 5 +- .../plugin/PinpointPluginTestStatement.java | 4 +- .../test/plugin/PinpointPluginTestSuite.java | 17 ++++++- 12 files changed, 132 insertions(+), 33 deletions(-) create mode 100644 agent/src/test/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionIT.java rename test/src/main/java/com/navercorp/pinpoint/test/plugin/{ChildProcessException.java => PinpointPluginTestException.java} (80%) diff --git a/agent/src/test/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionIT.java b/agent/src/test/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionIT.java new file mode 100644 index 000000000..b6cd86da2 --- /dev/null +++ b/agent/src/test/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionIT.java @@ -0,0 +1,51 @@ +/** + * Copyright 2014 NAVER Corp. + * Licensed 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 com.navercorp.pinpoint.profiler.modifier.connector.jdkhttpconnector; + +import java.net.HttpURLConnection; +import java.net.URL; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.navercorp.pinpoint.test.plugin.JvmVersion; +import com.navercorp.pinpoint.test.plugin.PinpointPluginTestSuite; + +/** + * @author Jongho Moon + * + */ +@RunWith(PinpointPluginTestSuite.class) +@JvmVersion({6, 7, 8}) +public class HttpURLConnectionIT { + + @Test + public void test() throws Exception { + URL url = new URL("http://www.naver.com"); + HttpURLConnection connection = (HttpURLConnection)url.openConnection(); + + System.out.println(connection.getHeaderFields()); + } + + @Test + public void testConnectTwice() throws Exception { + URL url = new URL("http://www.naver.com"); + HttpURLConnection connection = (HttpURLConnection)url.openConnection(); + + connection.connect(); + connection.connect(); + } + +} diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/instrument/InstrumentClass.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/instrument/InstrumentClass.java index c390c1a31..2cf452f50 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/instrument/InstrumentClass.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/instrument/InstrumentClass.java @@ -110,6 +110,8 @@ public interface InstrumentClass { boolean hasDeclaredMethod(String methodName, String[] args); boolean hasMethod(String methodName, String[] parameterTypeArray, String returnType); + + boolean hasField(String name, String type); InstrumentClass getNestedClass(String className); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClass.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClass.java index 8a0207c2d..4737b256d 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClass.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClass.java @@ -911,6 +911,17 @@ public class JavaAssistClass implements InstrumentClass { return false; } } + + @Override + public boolean hasField(String name, String type) { + try { + ctClass.getField(name, type); + } catch (NotFoundException e) { + return false; + } + + return true; + } @Override public InstrumentClass getNestedClass(String className) { @@ -939,7 +950,7 @@ public class JavaAssistClass implements InstrumentClass { try { // FIXME Which is better? getField() or getDeclaredField()? getFiled() seems like better chioce if we want to add getter to child classes. CtField traceVariable = ctClass.getField(variableName); - CtMethod getterMethod = CtNewMethod.getter(getterName, traceVariable); + CtMethod getterMethod = CtNewMethod.make("public " + traceVariable.getType().getName() + " " + getterName + "() { return " + variableName + "; }", ctClass); ctClass.addMethod(getterMethod); } catch (NotFoundException ex) { throw new InstrumentException(variableName + " addVariableAccessor fail. Cause:" + ex.getMessage(), ex); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionModifier.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionModifier.java index 60ef94305..dc6ed8684 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionModifier.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionModifier.java @@ -18,6 +18,9 @@ package com.navercorp.pinpoint.profiler.modifier.connector.jdkhttpconnector; import java.security.ProtectionDomain; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.navercorp.pinpoint.bootstrap.Agent; import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; @@ -25,15 +28,13 @@ import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException; import com.navercorp.pinpoint.profiler.modifier.AbstractModifier; import com.navercorp.pinpoint.profiler.modifier.connector.jdkhttpconnector.interceptor.ConnectMethodInterceptor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * TODO Fix class loader issue. * @author netspider * */ public class HttpURLConnectionModifier extends AbstractModifier { + private final static String SCOPE = "HttpURLConnectoin"; private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -52,9 +53,22 @@ public class HttpURLConnectionModifier extends AbstractModifier { try { InstrumentClass aClass = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer); + ConnectMethodInterceptor connectMethodInterceptor = new ConnectMethodInterceptor(); - aClass.addInterceptor("connect", null, connectMethodInterceptor); - + aClass.addScopeInterceptor("connect", null, connectMethodInterceptor, SCOPE); + + ConnectMethodInterceptor getInputStreamInterceptor = new ConnectMethodInterceptor(); + aClass.addScopeInterceptor("getInputStream", null, getInputStreamInterceptor, SCOPE); + + ConnectMethodInterceptor getOutputStreamInterceptor = new ConnectMethodInterceptor(); + aClass.addScopeInterceptor("getOutputStream", null, getOutputStreamInterceptor, SCOPE); + + aClass.addGetter("__isConnected", "connected", "boolean"); + + if (aClass.hasField("connecting", "boolean")) { + aClass.addGetter("__isConnecting", "connecting", "boolean"); + } + return aClass.toBytecode(); } catch (InstrumentException e) { logger.warn("HttpURLConnectionModifier fail. Caused:", e.getMessage(), e); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/interceptor/ConnectMethodInterceptor.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/interceptor/ConnectMethodInterceptor.java index 4f86d02c4..f7f461cdb 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/interceptor/ConnectMethodInterceptor.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/interceptor/ConnectMethodInterceptor.java @@ -30,6 +30,7 @@ import com.navercorp.pinpoint.bootstrap.interceptor.TraceContextSupport; import com.navercorp.pinpoint.bootstrap.logging.PLogger; import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; import com.navercorp.pinpoint.bootstrap.sampler.SamplingFlagUtils; +import com.navercorp.pinpoint.bootstrap.util.MetaObject; import com.navercorp.pinpoint.common.AnnotationKey; import com.navercorp.pinpoint.common.ServiceType; @@ -38,6 +39,7 @@ import com.navercorp.pinpoint.common.ServiceType; * @author emeroad */ public class ConnectMethodInterceptor implements SimpleAroundInterceptor, ByteCodeMethodDescriptorSupport, TraceContextSupport { + private final MetaObject isConnected = new MetaObject("__isConnected"); private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); private final boolean isDebug = logger.isDebugEnabled(); @@ -56,10 +58,13 @@ public class ConnectMethodInterceptor implements SimpleAroundInterceptor, ByteCo } HttpURLConnection request = (HttpURLConnection) target; - + final boolean setRequestHeader = !isConnected.invoke(target); + final boolean sampling = trace.canSampled(); if (!sampling) { - request.setRequestProperty(Header.HTTP_SAMPLED.toString(), SamplingFlagUtils.SAMPLING_RATE_FALSE); + if (setRequestHeader) { + request.setRequestProperty(Header.HTTP_SAMPLED.toString(), SamplingFlagUtils.SAMPLING_RATE_FALSE); + } return; } @@ -70,15 +75,16 @@ public class ConnectMethodInterceptor implements SimpleAroundInterceptor, ByteCo TraceId nextId = trace.getTraceId().getNextTraceId(); trace.recordNextSpanId(nextId.getSpanId()); - - request.setRequestProperty(Header.HTTP_TRACE_ID.toString(), nextId.getTransactionId()); - request.setRequestProperty(Header.HTTP_SPAN_ID.toString(), String.valueOf(nextId.getSpanId())); - request.setRequestProperty(Header.HTTP_PARENT_SPAN_ID.toString(), String.valueOf(nextId.getParentSpanId())); - - request.setRequestProperty(Header.HTTP_FLAGS.toString(), String.valueOf(nextId.getFlags())); - request.setRequestProperty(Header.HTTP_PARENT_APPLICATION_NAME.toString(), traceContext.getApplicationName()); - request.setRequestProperty(Header.HTTP_PARENT_APPLICATION_TYPE.toString(), Short.toString(traceContext.getServerTypeCode())); - + if (setRequestHeader) { + request.setRequestProperty(Header.HTTP_TRACE_ID.toString(), nextId.getTransactionId()); + request.setRequestProperty(Header.HTTP_SPAN_ID.toString(), String.valueOf(nextId.getSpanId())); + request.setRequestProperty(Header.HTTP_PARENT_SPAN_ID.toString(), String.valueOf(nextId.getParentSpanId())); + + request.setRequestProperty(Header.HTTP_FLAGS.toString(), String.valueOf(nextId.getFlags())); + request.setRequestProperty(Header.HTTP_PARENT_APPLICATION_NAME.toString(), traceContext.getApplicationName()); + request.setRequestProperty(Header.HTTP_PARENT_APPLICATION_TYPE.toString(), Short.toString(traceContext.getServerTypeCode())); + } + trace.recordServiceType(ServiceType.JDK_HTTPURLCONNECTOR); final URL url = request.getURL(); diff --git a/test/src/main/java/com/navercorp/pinpoint/test/plugin/DependencyResolver.java b/test/src/main/java/com/navercorp/pinpoint/test/plugin/DependencyResolver.java index bdfa9a501..0bfd5c57f 100644 --- a/test/src/main/java/com/navercorp/pinpoint/test/plugin/DependencyResolver.java +++ b/test/src/main/java/com/navercorp/pinpoint/test/plugin/DependencyResolver.java @@ -18,7 +18,6 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -29,9 +28,6 @@ import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import com.navercorp.pinpoint.common.util.SimpleProperty; -import com.navercorp.pinpoint.common.util.SystemProperty; - import org.apache.maven.repository.internal.MavenRepositorySystemUtils; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; @@ -65,13 +61,15 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.navercorp.pinpoint.bootstrap.PinpointBootStrap; +import com.navercorp.pinpoint.common.util.SimpleProperty; +import com.navercorp.pinpoint.common.util.SystemProperty; /** * @author Jongho Moon * */ public class DependencyResolver { - private static final String FOLLOW_PRECEDING = "FOLLOW_PRECEDING"; + private static final String FOLLOW_PRECEEDING = "FOLLOW_PRECEEDING"; private static final String DEFAULT_LOCAL_REPOSITORY = "target/local-repo"; private static final Logger logger = Logger.getLogger(PinpointBootStrap.class.getName()); @@ -241,12 +239,12 @@ public class DependencyResolver { int second = a.indexOf(':', first + 1); if (second == -1) { - a += ":" + FOLLOW_PRECEDING; + a += ":" + FOLLOW_PRECEEDING; } DefaultArtifact artifact = new DefaultArtifact(a); - if (FOLLOW_PRECEDING.equals(artifact.getVersion())) { + if (FOLLOW_PRECEEDING.equals(artifact.getVersion())) { if (lastCompanion != null) { lastCompanion.add(artifact); } else { diff --git a/test/src/main/java/com/navercorp/pinpoint/test/plugin/ForkedPinpointPluginTest.java b/test/src/main/java/com/navercorp/pinpoint/test/plugin/ForkedPinpointPluginTest.java index 8f65ae6cb..78593e90e 100644 --- a/test/src/main/java/com/navercorp/pinpoint/test/plugin/ForkedPinpointPluginTest.java +++ b/test/src/main/java/com/navercorp/pinpoint/test/plugin/ForkedPinpointPluginTest.java @@ -22,7 +22,6 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; -import java.util.regex.Pattern; import org.junit.runner.Description; import org.junit.runner.JUnitCore; diff --git a/test/src/main/java/com/navercorp/pinpoint/test/plugin/ForkedPinpointPluginTestRunner.java b/test/src/main/java/com/navercorp/pinpoint/test/plugin/ForkedPinpointPluginTestRunner.java index 0b9ffdc36..991bb6650 100644 --- a/test/src/main/java/com/navercorp/pinpoint/test/plugin/ForkedPinpointPluginTestRunner.java +++ b/test/src/main/java/com/navercorp/pinpoint/test/plugin/ForkedPinpointPluginTestRunner.java @@ -59,8 +59,11 @@ public class ForkedPinpointPluginTestRunner extends BlockJUnit4ClassRunner { PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); verifier.initialize(manageTraceObject); - fromSuper.evaluate(); - verifier.cleanUp(manageTraceObject); + try { + fromSuper.evaluate(); + } finally { + verifier.cleanUp(manageTraceObject); + } } }; } diff --git a/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestConstants.java b/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestConstants.java index d8988fe28..81bce378f 100644 --- a/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestConstants.java +++ b/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestConstants.java @@ -14,7 +14,6 @@ */ package com.navercorp.pinpoint.test.plugin; -import java.util.regex.Pattern; /** * @author Jongho Moon diff --git a/test/src/main/java/com/navercorp/pinpoint/test/plugin/ChildProcessException.java b/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestException.java similarity index 80% rename from test/src/main/java/com/navercorp/pinpoint/test/plugin/ChildProcessException.java rename to test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestException.java index 07e29735a..b3c4b2f3c 100644 --- a/test/src/main/java/com/navercorp/pinpoint/test/plugin/ChildProcessException.java +++ b/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestException.java @@ -18,8 +18,9 @@ package com.navercorp.pinpoint.test.plugin; * @author Jongho Moon * */ -public class ChildProcessException extends Exception { - public ChildProcessException(String message, StackTraceElement[] stackTrace) { +@SuppressWarnings("serial") +public class PinpointPluginTestException extends Exception { + public PinpointPluginTestException(String message, StackTraceElement[] stackTrace) { super(message); setStackTrace(stackTrace); } diff --git a/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestStatement.java b/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestStatement.java index 3042a9155..73c454a51 100644 --- a/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestStatement.java +++ b/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestStatement.java @@ -214,7 +214,7 @@ public class PinpointPluginTestStatement extends Statement implements PinpointPl return failure; } - private ChildProcessException toException(String message, String exceptionClass, List traceInText) { + private PinpointPluginTestException toException(String message, String exceptionClass, List traceInText) { StackTraceElement[] stackTrace = new StackTraceElement[traceInText.size()]; for (int i = 0; i < traceInText.size(); i++) { @@ -224,6 +224,6 @@ public class PinpointPluginTestStatement extends Statement implements PinpointPl stackTrace[i] = new StackTraceElement(tokens[0], tokens[1], tokens[2], Integer.parseInt(tokens[3])); } - return new ChildProcessException(exceptionClass + ": " + message, stackTrace); + return new PinpointPluginTestException(exceptionClass + ": " + message, stackTrace); } } diff --git a/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestSuite.java b/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestSuite.java index 521082118..0b8ea9e31 100644 --- a/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestSuite.java +++ b/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestSuite.java @@ -18,6 +18,7 @@ import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Scanner; @@ -83,7 +84,21 @@ public class PinpointPluginTestSuite extends AbstractPinpointPluginTestSuite imp return createCasesWithLibraryPath(context); } - throw new IllegalStateException("Cannot happen"); + return createCasesWithJdkOnly(context); + } + + private List createCasesWithJdkOnly(PinpointPluginTestContext context) { + List cases = new ArrayList(); + + if (testOnSystemClassLoader) { + cases.add(new NormalPluginTestCase(context, "", Collections.emptyList(), true)); + } + + if (testOnChildClassLoader) { + cases.add(new NormalPluginTestCase(context, "", Collections.emptyList(), false)); + } + + return cases; } From b09d8c0e1151114b3461d7026d4f8a5b3f096b75 Mon Sep 17 00:00:00 2001 From: Jongho Moon Date: Thu, 19 Mar 2015 14:09:14 +0900 Subject: [PATCH 8/9] Some tests require JDK8, but for now JDK8 is not mandatory to build Pinpoint. So skip test if it cannot find required java installation. --- .../test/plugin/AbstractPinpointPluginTestSuite.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/src/main/java/com/navercorp/pinpoint/test/plugin/AbstractPinpointPluginTestSuite.java b/test/src/main/java/com/navercorp/pinpoint/test/plugin/AbstractPinpointPluginTestSuite.java index db491b213..621f2ac53 100644 --- a/test/src/main/java/com/navercorp/pinpoint/test/plugin/AbstractPinpointPluginTestSuite.java +++ b/test/src/main/java/com/navercorp/pinpoint/test/plugin/AbstractPinpointPluginTestSuite.java @@ -99,6 +99,10 @@ public abstract class AbstractPinpointPluginTestSuite extends Suite { javaHome = SystemProperty.INSTANCE.getEnv(envName); } + if (javaHome == null) { + return null; + } + builder.append(javaHome); builder.append(File.separatorChar); builder.append("bin"); @@ -219,6 +223,14 @@ public abstract class AbstractPinpointPluginTestSuite extends Suite { try { for (int ver : jvmVersions) { String javaExe = getJavaExecutable(ver); + + // TODO for now, java 8 is not mandatory to build pinpoint. + // so failing to find java installation should not cause build failure. + if (javaExe == null) { + System.out.println("Cannot find Java version " + ver + ". Skip test with Java " + ver); + continue; + } + PinpointPluginTestContext context = new PinpointPluginTestContext(agentJar, configFile, requiredLibraries, getTestClass().getJavaClass(), testClassLocation, jvmArguments, debug, ver, javaExe); List cases = createTestCases(context); From 1ffd0c6a6ebd529c3fa7548154d9e4d00fb20190 Mon Sep 17 00:00:00 2001 From: Jongho Moon Date: Mon, 23 Mar 2015 15:54:52 +0900 Subject: [PATCH 9/9] [#117] Implemented JDK-HTTP plugin - added attributes to Trace - added trace block attachment to Trace - changed ClassEditorBuilder.condition() to conditional() --- agent/pom.xml | 6 +- .../jdk/http}/HttpURLConnectionIT.java | 27 ++- .../bootstrap/context/RecordableTrace.java | 8 +- .../bootstrap/context/StackOperation.java | 5 + ...ctor.java => ApplicationTypeDetector.java} | 4 +- .../bootstrap/plugin/ProfilerPlugin.java | 2 +- .../plugin/ProfilerPluginSetupContext.java | 4 +- .../plugin/editor/BaseClassEditorBuilder.java | 41 +++++ .../editor/BaseMethodEditorBuilder.java | 1 - .../plugin/editor/ClassCondition.java | 3 +- .../plugin/editor/ClassConditions.java | 93 ++++++++++ .../plugin/editor/ClassEditorBuilder.java | 25 +-- .../editor/ConditionalClassEditorBuilder.java | 23 +++ .../editor/ConditionalClassEditorSetup.java | 23 +++ .../ApplicationServerTypePluginResolver.java | 14 +- .../bootstrap/interceptor/MockTrace.java | 43 ++++- .../pinpoint/common/ServiceType.java | 62 ++++++- .../pinpoint/common/TypeProviderLoader.java | 2 +- .../pinpoint/common/plugin/TypeProvider.java | 2 +- .../common/util/DefaultDisplayArgument.java | 1 - .../common/ServiceTypeInitializerTest.java | 2 +- plugins/jdk-http/.gitignore | 4 + plugins/jdk-http/pom.xml | 26 +++ .../plugin/jdk/http/JdkHttpConstants.java | 27 +++ .../plugin/jdk/http/JdkHttpPlugin.java | 53 ++++++ .../plugin/jdk/http/JdkHttpTypeProvider.java | 33 ++++ .../HttpURLConnectionInterceptor.java | 162 ++++++++++++++++++ ...p.pinpoint.bootstrap.plugin.ProfilerPlugin | 1 + ...ercorp.pinpoint.common.plugin.TypeProvider | 1 + plugins/pom.xml | 18 +- .../pinpoint/plugin/redis/RedisPlugin.java | 11 +- .../plugin/redis/RedisTypeProvider.java | 2 +- .../plugin/servlet/ServletPlugin.java | 5 +- .../plugin/servlet/ServletTypeProvider.java | 2 +- .../plugin/tomcat/TomcatDetector.java | 4 +- .../pinpoint/plugin/tomcat/TomcatPlugin.java | 19 +- .../plugin/tomcat/TomcatTypeProvider.java | 2 +- .../pinpoint/profiler/DefaultAgent.java | 2 +- .../profiler/context/DefaultTrace.java | 46 ++++- .../profiler/context/DisableTrace.java | 35 ++++ .../profiler/context/MetricTrace.java | 43 ++++- .../profiler/context/RootStackFrame.java | 4 +- .../profiler/context/SpanEventStackFrame.java | 4 +- .../pinpoint/profiler/context/StackFrame.java | 2 +- .../interceptor/bci/JavaAssistClass.java | 37 +++- .../modifier/DefaultModifierRegistry.java | 4 - .../interceptor/ConnectMethodInterceptor.java | 2 +- .../plugin/DefaultProfilerPluginContext.java | 14 +- .../plugin/PluginClassLoaderFactory.java | 37 +++- ...ditor.java => ConditionalClassRecipe.java} | 25 ++- .../editor/ConditionalMethodEditor.java | 7 +- .../editor/DefaultClassEditorBuilder.java | 78 ++++----- .../profiler/plugin/editor/RecipeBuilder.java | 23 +++ .../util/ApplicationServerTypeResolver.java | 12 +- .../pinpoint/test/PluginTestAgent.java | 8 +- .../interceptor/bci/JavaAssistClassTest.java | 16 +- .../profiler/interceptor/bci/TestObject3.java | 5 + .../plugin/DefaultClassEditorBuilderTest.java | 4 +- .../plugin/PinpointPluginTestException.java | 20 ++- 59 files changed, 1003 insertions(+), 186 deletions(-) rename agent/src/test/java/com/navercorp/pinpoint/{profiler/modifier/connector/jdkhttpconnector => plugin/jdk/http}/HttpURLConnectionIT.java (51%) rename bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/{ServerTypeDetector.java => ApplicationTypeDetector.java} (96%) create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/BaseClassEditorBuilder.java create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassConditions.java create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ConditionalClassEditorBuilder.java create mode 100644 bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ConditionalClassEditorSetup.java create mode 100644 plugins/jdk-http/.gitignore create mode 100644 plugins/jdk-http/pom.xml create mode 100644 plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpConstants.java create mode 100644 plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpPlugin.java create mode 100644 plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpTypeProvider.java create mode 100644 plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/interceptor/HttpURLConnectionInterceptor.java create mode 100644 plugins/jdk-http/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin create mode 100644 plugins/jdk-http/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.plugin.TypeProvider rename profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/{ConditionalClassEditor.java => ConditionalClassRecipe.java} (60%) create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/RecipeBuilder.java diff --git a/agent/pom.xml b/agent/pom.xml index abfa4256e..18ea9c101 100644 --- a/agent/pom.xml +++ b/agent/pom.xml @@ -88,7 +88,11 @@ - + + + false + + org.apache.maven.plugins maven-assembly-plugin diff --git a/agent/src/test/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionIT.java b/agent/src/test/java/com/navercorp/pinpoint/plugin/jdk/http/HttpURLConnectionIT.java similarity index 51% rename from agent/src/test/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionIT.java rename to agent/src/test/java/com/navercorp/pinpoint/plugin/jdk/http/HttpURLConnectionIT.java index b6cd86da2..e6121ddf3 100644 --- a/agent/src/test/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/HttpURLConnectionIT.java +++ b/agent/src/test/java/com/navercorp/pinpoint/plugin/jdk/http/HttpURLConnectionIT.java @@ -12,14 +12,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.navercorp.pinpoint.profiler.modifier.connector.jdkhttpconnector; +package com.navercorp.pinpoint.plugin.jdk.http; +import static com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier.ExpectedAnnotation.*; + +import java.lang.reflect.Method; import java.net.HttpURLConnection; import java.net.URL; import org.junit.Test; import org.junit.runner.RunWith; +import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier; +import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifierHolder; import com.navercorp.pinpoint.test.plugin.JvmVersion; import com.navercorp.pinpoint.test.plugin.PinpointPluginTestSuite; @@ -35,8 +40,15 @@ public class HttpURLConnectionIT { public void test() throws Exception { URL url = new URL("http://www.naver.com"); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); + connection.getHeaderFields(); - System.out.println(connection.getHeaderFields()); + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + + Class targetClass = Class.forName("sun.net.www.protocol.http.HttpURLConnection"); + Method getInputStream = targetClass.getMethod("getInputStream"); + + verifier.verifySpanCount(1); + verifier.verifySpanEvent("JDK_HTTPURLCONNECTOR", getInputStream, null, null, "www.naver.com", annotation("http.url", "http://www.naver.com")); } @Test @@ -45,7 +57,16 @@ public class HttpURLConnectionIT { HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.connect(); - connection.connect(); + connection.getInputStream(); + + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + verifier.printSpans(System.out); + + Class targetClass = Class.forName("sun.net.www.protocol.http.HttpURLConnection"); + Method connect = targetClass.getMethod("connect"); + + verifier.verifySpanCount(1); + verifier.verifySpanEvent("JDK_HTTPURLCONNECTOR", connect, null, null, "www.naver.com", annotation("http.url", "http://www.naver.com")); } } diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/context/RecordableTrace.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/context/RecordableTrace.java index fe07cff6f..5618a7e3f 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/context/RecordableTrace.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/context/RecordableTrace.java @@ -93,4 +93,10 @@ public interface RecordableTrace { void recordAcceptorHost(String host); int getStackFrameId(); -} + + Object getAttribute(String key); + + Object setAttribute(String key, Object value); + + Object removeAttribute(String key); +} \ No newline at end of file diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/context/StackOperation.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/context/StackOperation.java index 204a73b08..088e1b7e5 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/context/StackOperation.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/context/StackOperation.java @@ -36,4 +36,9 @@ public interface StackOperation { void traceBlockEnd(); void traceBlockEnd(int stackId); + + + Object setTraceBlockAttachment(Object attachment); + Object getTraceBlockAttachment(); + Object removeTraceBlockAttachment(); } diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ServerTypeDetector.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ApplicationTypeDetector.java similarity index 96% rename from bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ServerTypeDetector.java rename to bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ApplicationTypeDetector.java index d53952107..a818d0503 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ServerTypeDetector.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ApplicationTypeDetector.java @@ -17,12 +17,12 @@ package com.navercorp.pinpoint.bootstrap.plugin; import com.navercorp.pinpoint.bootstrap.resolver.ConditionProvider; import com.navercorp.pinpoint.common.ServiceType; + /** * @author Jongho Moon - * @author HyunGil Jeong * */ -public interface ServerTypeDetector { +public interface ApplicationTypeDetector { /** * Returns the {@link ServiceType} representing the current plugin, diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ProfilerPlugin.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ProfilerPlugin.java index bab4f24cd..d30c9865a 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ProfilerPlugin.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ProfilerPlugin.java @@ -19,5 +19,5 @@ package com.navercorp.pinpoint.bootstrap.plugin; public interface ProfilerPlugin { - void setUp(ProfilerPluginSetupContext context); + void setup(ProfilerPluginSetupContext context); } diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ProfilerPluginSetupContext.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ProfilerPluginSetupContext.java index 8b56a1ba6..129e435eb 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ProfilerPluginSetupContext.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/ProfilerPluginSetupContext.java @@ -28,8 +28,8 @@ public interface ProfilerPluginSetupContext { public Object setAttribute(String key, Object value); public Object getAttribute(String key); - public ClassEditorBuilder newClassEditorBuilder(); + public ClassEditorBuilder getClassEditorBuilder(String targetClassName); public void addClassEditor(ClassEditor classEditor); - public void addServerTypeDetector(ServerTypeDetector... detectors); + public void addApplicationTypeDetector(ApplicationTypeDetector... detectors); } diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/BaseClassEditorBuilder.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/BaseClassEditorBuilder.java new file mode 100644 index 000000000..97cbfebab --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/BaseClassEditorBuilder.java @@ -0,0 +1,41 @@ +/** + * Copyright 2014 NAVER Corp. + * Licensed 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 com.navercorp.pinpoint.bootstrap.plugin.editor; + +import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter; + +/** + * @author Jongho Moon + * + */ +public interface BaseClassEditorBuilder { + + public abstract void injectFieldAccessor(String fieldName); + + public abstract void injectMetadata(String name); + + public abstract void injectMetadata(String name, String initialValueType); + + public abstract void injectInterceptor(String className, Object... constructorArgs); + + public abstract void weave(String aspectClassName); + + public abstract MethodEditorBuilder editMethods(MethodFilter filter); + + public abstract MethodEditorBuilder editMethod(String name, String... parameterTypeNames); + + public abstract ConstructorEditorBuilder editConstructor(String... parameterTypeNames); + +} \ No newline at end of file diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/BaseMethodEditorBuilder.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/BaseMethodEditorBuilder.java index 6387eb7e9..4f4811ab9 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/BaseMethodEditorBuilder.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/BaseMethodEditorBuilder.java @@ -19,7 +19,6 @@ package com.navercorp.pinpoint.bootstrap.plugin.editor; * */ public interface BaseMethodEditorBuilder { - void condition(ClassCondition condition); void injectInterceptor(String interceptorClassName, Object... constructorArguments); void exceptionHandler(MethodEditorExceptionHandler handler); void property(MethodEditorProperty... properties); diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassCondition.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassCondition.java index c0dd12dee..9c333e218 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassCondition.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassCondition.java @@ -17,7 +17,8 @@ package com.navercorp.pinpoint.bootstrap.plugin.editor; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; +import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginContext; public interface ClassCondition { - boolean check(ClassLoader classLoader, InstrumentClass target); + boolean check(ProfilerPluginContext context, ClassLoader classLoader, InstrumentClass target); } diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassConditions.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassConditions.java new file mode 100644 index 000000000..9bde418a8 --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassConditions.java @@ -0,0 +1,93 @@ +/** + * Copyright 2014 NAVER Corp. + * Licensed 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 com.navercorp.pinpoint.bootstrap.plugin.editor; + +import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; +import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginContext; + +/** + * @author Jongho Moon + * + */ +public class ClassConditions { + + public static ClassCondition hasField(String name) { + return new HasField(name); + } + + public static ClassCondition hasField(String name, String type) { + return new HasField(name, type); + } + + public static ClassCondition hasMethod(String name, String returnType, String... paramTypes) { + return new HasMethod(name, returnType, paramTypes); + } + + public static ClassCondition hasDeclaredMethod(String name, String... paramTypes) { + return new HasDeclaredMethod(name, paramTypes); + } + + + private static class HasField implements ClassCondition { + private final String name; + private final String type; + + public HasField(String name) { + this(name, null); + } + + public HasField(String name, String type) { + this.name = name; + this.type = type; + } + + @Override + public boolean check(ProfilerPluginContext context, ClassLoader classLoader, InstrumentClass target) { + return target.hasField(name, type); + } + } + + private static class HasMethod implements ClassCondition { + private final String name; + private final String returnType; + private final String[] paramTypes; + + public HasMethod(String name, String returnType, String... paramTypes) { + this.name = name; + this.returnType = returnType; + this.paramTypes = paramTypes; + } + + @Override + public boolean check(ProfilerPluginContext context, ClassLoader classLoader, InstrumentClass target) { + return target.hasMethod(name, paramTypes, returnType); + } + } + + private static class HasDeclaredMethod implements ClassCondition { + private final String name; + private final String[] paramTypes; + + public HasDeclaredMethod(String name, String[] paramTypes) { + this.name = name; + this.paramTypes = paramTypes; + } + + @Override + public boolean check(ProfilerPluginContext context, ClassLoader classLoader, InstrumentClass target) { + return target.hasDeclaredMethod(name, paramTypes); + } + } +} diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassEditorBuilder.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassEditorBuilder.java index 2daf3e4cc..bcb3758c2 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassEditorBuilder.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ClassEditorBuilder.java @@ -14,7 +14,6 @@ */ package com.navercorp.pinpoint.bootstrap.plugin.editor; -import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter; @@ -22,27 +21,7 @@ import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter; * @author Jongho Moon * */ -public interface ClassEditorBuilder { - - public void target(String targetClassName); - - public void condition(ClassCondition condition); - - public void injectFieldSnooper(String fieldName); - - public void injectMetadata(String name); - - public void injectMetadata(String name, String initialValueType); - - public void injectInterceptor(String className, Object... constructorArgs); - - public void weave(String aspectClassName); - - public MethodEditorBuilder editMethods(MethodFilter filter); - - public MethodEditorBuilder editMethod(String name, String... parameterTypeNames); - - public ConstructorEditorBuilder editConstructor(String... parameterTypeNames); - +public interface ClassEditorBuilder extends BaseClassEditorBuilder { + public void conditional(ClassCondition condition, ConditionalClassEditorSetup descriptor); public ClassEditor build(); } \ No newline at end of file diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ConditionalClassEditorBuilder.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ConditionalClassEditorBuilder.java new file mode 100644 index 000000000..c115ad35b --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ConditionalClassEditorBuilder.java @@ -0,0 +1,23 @@ +/** + * Copyright 2014 NAVER Corp. + * Licensed 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 com.navercorp.pinpoint.bootstrap.plugin.editor; + +/** + * @author Jongho Moon + * + */ +public interface ConditionalClassEditorBuilder extends BaseClassEditorBuilder { + +} diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ConditionalClassEditorSetup.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ConditionalClassEditorSetup.java new file mode 100644 index 000000000..3fd33ffa4 --- /dev/null +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/editor/ConditionalClassEditorSetup.java @@ -0,0 +1,23 @@ +/** + * Copyright 2014 NAVER Corp. + * Licensed 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 com.navercorp.pinpoint.bootstrap.plugin.editor; + +/** + * @author Jongho Moon + * + */ +public interface ConditionalClassEditorSetup { + public void setup(ConditionalClassEditorBuilder conditional); +} diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ApplicationServerTypePluginResolver.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ApplicationServerTypePluginResolver.java index 78e51366f..55ae94214 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ApplicationServerTypePluginResolver.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/resolver/ApplicationServerTypePluginResolver.java @@ -20,7 +20,7 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import com.navercorp.pinpoint.bootstrap.plugin.ServerTypeDetector; +import com.navercorp.pinpoint.bootstrap.plugin.ApplicationTypeDetector; import com.navercorp.pinpoint.common.ServiceType; /** @@ -35,29 +35,29 @@ public class ApplicationServerTypePluginResolver { private final Logger logger = Logger.getLogger(ApplicationServerTypePluginResolver.class.getName()); - private final List serverTypeDetectors; + private final List applicationTypeDetectors; private final ConditionProvider conditionProvider; private static final ServiceType DEFAULT_SERVER_TYPE = ServiceType.STAND_ALONE; - public ApplicationServerTypePluginResolver(List serverTypeDetectors) { + public ApplicationServerTypePluginResolver(List serverTypeDetectors) { this(serverTypeDetectors, ConditionProvider.DEFAULT_CONDITION_PROVIDER); } - public ApplicationServerTypePluginResolver(List serverTypeDetectors, ConditionProvider conditionProvider) { + public ApplicationServerTypePluginResolver(List serverTypeDetectors, ConditionProvider conditionProvider) { if (serverTypeDetectors == null) { - throw new IllegalArgumentException("serverTypeDetectors should not be null"); + throw new IllegalArgumentException("applicationTypeDetectors should not be null"); } if (conditionProvider == null) { throw new IllegalArgumentException("conditionProvider should not be null"); } - this.serverTypeDetectors = serverTypeDetectors; + this.applicationTypeDetectors = serverTypeDetectors; this.conditionProvider = conditionProvider; } public ServiceType resolve() { - for (ServerTypeDetector currentDetector : this.serverTypeDetectors) { + for (ApplicationTypeDetector currentDetector : this.applicationTypeDetectors) { logger.log(Level.INFO, "Attempting to resolve using " + currentDetector.getClass()); if (currentDetector.detect(this.conditionProvider)) { logger.log(Level.INFO, "Match found using " + currentDetector.getClass().getSimpleName()); diff --git a/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/interceptor/MockTrace.java b/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/interceptor/MockTrace.java index 05c1714b1..53fd9374c 100644 --- a/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/interceptor/MockTrace.java +++ b/bootstrap/src/test/java/com/navercorp/pinpoint/bootstrap/interceptor/MockTrace.java @@ -16,9 +16,11 @@ package com.navercorp.pinpoint.bootstrap.interceptor; +import java.util.HashMap; +import java.util.Map; + import com.navercorp.pinpoint.bootstrap.context.Trace; import com.navercorp.pinpoint.bootstrap.context.TraceId; -import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor; import com.navercorp.pinpoint.common.AnnotationKey; import com.navercorp.pinpoint.common.ServiceType; import com.navercorp.pinpoint.common.util.Clock; @@ -36,7 +38,10 @@ public class MockTrace implements Trace { private boolean sampled = true; private Clock clock = SystemClock.INSTANCE; - + + private final Map attributeMap = new HashMap(); + private Object attachment; + public void setClock(Clock clock) { this.clock = clock; } @@ -214,4 +219,38 @@ public class MockTrace implements Trace { public short getServiceType() { return ServiceType.UNDEFINED.getCode(); } + + @Override + public Object getAttribute(String key) { + return attributeMap.get(key); + } + + @Override + public Object setAttribute(String key, Object value) { + return attributeMap.put(key, value); + } + + @Override + public Object removeAttribute(String key) { + return attributeMap.remove(key); + } + + @Override + public Object setTraceBlockAttachment(Object attachment) { + Object copy = this.attachment; + this.attachment = attachment; + return copy; + } + + @Override + public Object getTraceBlockAttachment() { + return this.attachment; + } + + @Override + public Object removeTraceBlockAttachment() { + Object copy = this.attachment; + this.attachment = null; + return copy; + } } diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/ServiceType.java b/commons/src/main/java/com/navercorp/pinpoint/common/ServiceType.java index 26e46f8cf..f51e8eb3f 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/ServiceType.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/ServiceType.java @@ -149,6 +149,66 @@ public class ServiceType { public String toString() { return desc; } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null) { + return false; + } + + if (getClass() != obj.getClass()) { + return false; + } + + ServiceType other = (ServiceType) obj; + if (code != other.code) { + return false; + } + if (desc == null) { + if (other.desc != null) { + return false; + } + } else if (!desc.equals(other.desc)) { + return false; + + } + + if (histogramSchema == null) { + if (other.histogramSchema != null) { + return false; + } + } else if (!histogramSchema.equals(other.histogramSchema)) { + return false; + } + + if (includeDestinationId != other.includeDestinationId) { + return false; + } + + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + + if (recordStatistics != other.recordStatistics) { + return false; + } + + if (terminal != other.terminal) { + return false; + } + + return true; + } + + // Undefined Service Code public static final ServiceType UNDEFINED = of(-1, "UNDEFINED", NORMAL_SCHEMA, TERMINAL); @@ -215,7 +275,7 @@ public class ServiceType { // Connector, Client public static final ServiceType HTTP_CLIENT = of(9050, "HTTP_CLIENT", NORMAL_SCHEMA, RECORD_STATISTICS); public static final ServiceType HTTP_CLIENT_INTERNAL = of(9051, "HTTP_CLIENT_INTERNAL", "HTTP_CLIENT", NORMAL_SCHEMA); - public static final ServiceType JDK_HTTPURLCONNECTOR = of(9055, "JDK_HTTPURLCONNECTOR", "JDK_HTTPCONNECTOR", NORMAL_SCHEMA); +// public static final ServiceType JDK_HTTPURLCONNECTOR = of(9055, "JDK_HTTPURLCONNECTOR", "JDK_HTTPCONNECTOR", NORMAL_SCHEMA); public static final ServiceType NPC_CLIENT = of(9060, "NPC_CLIENT", NORMAL_SCHEMA, RECORD_STATISTICS); public static final ServiceType NIMM_CLIENT = of(9070, "NIMM_CLIENT", NORMAL_SCHEMA, RECORD_STATISTICS); diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/TypeProviderLoader.java b/commons/src/main/java/com/navercorp/pinpoint/common/TypeProviderLoader.java index 1f1ae4cc1..0de27e94b 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/TypeProviderLoader.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/TypeProviderLoader.java @@ -78,7 +78,7 @@ public class TypeProviderLoader { } TypeSetupContextImpl context = new TypeSetupContextImpl(provider.getClass()); - provider.setUp(context); + provider.setup(context); setupContextList.add(context); diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/plugin/TypeProvider.java b/commons/src/main/java/com/navercorp/pinpoint/common/plugin/TypeProvider.java index 24e6765d9..894997b6f 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/plugin/TypeProvider.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/plugin/TypeProvider.java @@ -20,5 +20,5 @@ package com.navercorp.pinpoint.common.plugin; * */ public interface TypeProvider { - void setUp(TypeSetupContext context); + void setup(TypeSetupContext context); } diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/util/DefaultDisplayArgument.java b/commons/src/main/java/com/navercorp/pinpoint/common/util/DefaultDisplayArgument.java index 4d734cad8..bb441342e 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/util/DefaultDisplayArgument.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/util/DefaultDisplayArgument.java @@ -53,7 +53,6 @@ public class DefaultDisplayArgument { public static final DisplayArgumentMatcher HTTP_CLIENT_MATCHER = createArgumentMatcher(ServiceType.HTTP_CLIENT, AnnotationKey.HTTP_URL); public static final DisplayArgumentMatcher HTTP_CLIENT_INTERNAL_MATCHER = createArgumentMatcher(ServiceType.HTTP_CLIENT_INTERNAL, AnnotationKey.HTTP_CALL_RETRY_COUNT); - public static final DisplayArgumentMatcher JDK_HTTPURLCONNECTOR_MATCHER = createArgumentMatcher(ServiceType.JDK_HTTPURLCONNECTOR, AnnotationKey.HTTP_URL); diff --git a/commons/src/test/java/com/navercorp/pinpoint/common/ServiceTypeInitializerTest.java b/commons/src/test/java/com/navercorp/pinpoint/common/ServiceTypeInitializerTest.java index 66d506f9a..94fc22a33 100644 --- a/commons/src/test/java/com/navercorp/pinpoint/common/ServiceTypeInitializerTest.java +++ b/commons/src/test/java/com/navercorp/pinpoint/common/ServiceTypeInitializerTest.java @@ -150,7 +150,7 @@ public class ServiceTypeInitializerTest { } @Override - public void setUp(TypeSetupContext context) { + public void setup(TypeSetupContext context) { for (ServiceType type : serviceTypes) { context.addType(type); } diff --git a/plugins/jdk-http/.gitignore b/plugins/jdk-http/.gitignore new file mode 100644 index 000000000..8bd3a0588 --- /dev/null +++ b/plugins/jdk-http/.gitignore @@ -0,0 +1,4 @@ +/target/ +/.settings/ +/.classpath +/.project diff --git a/plugins/jdk-http/pom.xml b/plugins/jdk-http/pom.xml new file mode 100644 index 000000000..b75de18ab --- /dev/null +++ b/plugins/jdk-http/pom.xml @@ -0,0 +1,26 @@ + + 4.0.0 + + com.navercorp.pinpoint + pom + ../.. + 1.1.0-SNAPSHOT + + + pinpoint-jdk-http-plugin + pinpoint-jdk-http-plugin + jar + + + + + com.navercorp.pinpoint + pinpoint-profiler + + + + diff --git a/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpConstants.java b/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpConstants.java new file mode 100644 index 000000000..9c984bcca --- /dev/null +++ b/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpConstants.java @@ -0,0 +1,27 @@ +/** + * Copyright 2014 NAVER Corp. + * Licensed 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 com.navercorp.pinpoint.plugin.jdk.http; + +import static com.navercorp.pinpoint.common.HistogramSchema.*; + +import com.navercorp.pinpoint.common.ServiceType; + +/** + * @author Jongho Moon + * + */ +public interface JdkHttpConstants { + public static final ServiceType SERVICE_TYPE = ServiceType.of(9055, "JDK_HTTPURLCONNECTOR", "JDK_HTTPCONNECTOR", NORMAL_SCHEMA); +} diff --git a/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpPlugin.java b/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpPlugin.java new file mode 100644 index 000000000..d918e92dd --- /dev/null +++ b/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpPlugin.java @@ -0,0 +1,53 @@ +package com.navercorp.pinpoint.plugin.jdk.http; +/* + * Copyright 2014 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import static com.navercorp.pinpoint.bootstrap.plugin.editor.ClassConditions.*; + +import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin; +import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginSetupContext; +import com.navercorp.pinpoint.bootstrap.plugin.editor.ClassEditorBuilder; +import com.navercorp.pinpoint.bootstrap.plugin.editor.ConditionalClassEditorBuilder; +import com.navercorp.pinpoint.bootstrap.plugin.editor.ConditionalClassEditorSetup; + +/** + * + * @author Jongho Moon + * + */ +public class JdkHttpPlugin implements ProfilerPlugin { + + @Override + public void setup(ProfilerPluginSetupContext context) { + ClassEditorBuilder builder = context.getClassEditorBuilder("sun.net.www.protocol.http.HttpURLConnection"); + + builder.injectFieldAccessor("connected"); + builder.injectInterceptor("com.navercorp.pinpoint.plugin.jdk.http.interceptor.HttpURLConnectionInterceptor"); + + // JDK 8 + builder.conditional(hasField("connecting", "boolean"), + new ConditionalClassEditorSetup() { + @Override + public void setup(ConditionalClassEditorBuilder conditional) { + conditional.injectFieldAccessor("connecting"); + } + } + ); + + context.addClassEditor(builder.build()); + } + +} diff --git a/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpTypeProvider.java b/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpTypeProvider.java new file mode 100644 index 000000000..d069f9e61 --- /dev/null +++ b/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/JdkHttpTypeProvider.java @@ -0,0 +1,33 @@ +/** + * Copyright 2014 NAVER Corp. + * Licensed 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 com.navercorp.pinpoint.plugin.jdk.http; + +import com.navercorp.pinpoint.common.AnnotationKey; +import com.navercorp.pinpoint.common.AnnotationKeyMatcher.ExactMatcher; +import com.navercorp.pinpoint.common.plugin.TypeProvider; +import com.navercorp.pinpoint.common.plugin.TypeSetupContext; + +/** + * @author Jongho Moon + * + */ +public class JdkHttpTypeProvider implements TypeProvider, JdkHttpConstants { + + @Override + public void setup(TypeSetupContext context) { + context.addType(SERVICE_TYPE, new ExactMatcher(AnnotationKey.HTTP_URL)); + } + +} diff --git a/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/interceptor/HttpURLConnectionInterceptor.java b/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/interceptor/HttpURLConnectionInterceptor.java new file mode 100644 index 000000000..09e9536df --- /dev/null +++ b/plugins/jdk-http/src/main/java/com/navercorp/pinpoint/plugin/jdk/http/interceptor/HttpURLConnectionInterceptor.java @@ -0,0 +1,162 @@ +/* + * Copyright 2014 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.plugin.jdk.http.interceptor; + +import java.net.HttpURLConnection; +import java.net.URL; + +import com.navercorp.pinpoint.bootstrap.FieldAccessor; +import com.navercorp.pinpoint.bootstrap.context.Header; +import com.navercorp.pinpoint.bootstrap.context.Trace; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.context.TraceId; +import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor; +import com.navercorp.pinpoint.bootstrap.logging.PLogger; +import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; +import com.navercorp.pinpoint.bootstrap.plugin.Cached; +import com.navercorp.pinpoint.bootstrap.plugin.Name; +import com.navercorp.pinpoint.bootstrap.plugin.Scope; +import com.navercorp.pinpoint.bootstrap.plugin.TargetMethod; +import com.navercorp.pinpoint.bootstrap.plugin.Targets; +import com.navercorp.pinpoint.bootstrap.sampler.SamplingFlagUtils; +import com.navercorp.pinpoint.common.AnnotationKey; +import com.navercorp.pinpoint.plugin.jdk.http.JdkHttpConstants; + +/** + * @author netspider + * @author emeroad + */ +@Scope("HttpURLConnection") +@Targets(methods={ + @TargetMethod(name="connect"), + @TargetMethod(name="getInputStream"), + @TargetMethod(name="getOutputStream") +}) +public class HttpURLConnectionInterceptor implements SimpleAroundInterceptor, JdkHttpConstants { + /** + * + */ + private static final Object TRACE_BLOCK_BEGIN_MARKER = new Object(); + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private final TraceContext traceContext; + private final MethodDescriptor descriptor; + private final FieldAccessor connectedAccessor; + private final FieldAccessor connectingAccessor; + + public HttpURLConnectionInterceptor(TraceContext traceContext, @Cached MethodDescriptor descriptor, @Name("connected") FieldAccessor connectedAccessor, @Name("connecting") FieldAccessor connectingAccessor) { + this.traceContext = traceContext; + this.descriptor = descriptor; + this.connectedAccessor = connectedAccessor; + this.connectingAccessor = connectingAccessor; + } + + @Override + public void before(Object target, Object[] args) { + if (isDebug) { + logger.beforeInterceptor(target, args); + } + Trace trace = traceContext.currentRawTraceObject(); + if (trace == null) { + return; + } + + HttpURLConnection request = (HttpURLConnection) target; + + boolean connected = (Boolean)connectedAccessor.get(target); + boolean connecting = connectingAccessor.isApplicable(target) && (Boolean)connectingAccessor.get(target); + + if (connected || connecting) { + return; + } + + final boolean sampling = trace.canSampled(); + if (!sampling) { + request.setRequestProperty(Header.HTTP_SAMPLED.toString(), SamplingFlagUtils.SAMPLING_RATE_FALSE); + return; + } + + trace.traceBlockBegin(); + trace.setTraceBlockAttachment(TRACE_BLOCK_BEGIN_MARKER); + trace.markBeforeTime(); + + TraceId nextId = trace.getTraceId().getNextTraceId(); + trace.recordNextSpanId(nextId.getSpanId()); + + request.setRequestProperty(Header.HTTP_TRACE_ID.toString(), nextId.getTransactionId()); + request.setRequestProperty(Header.HTTP_SPAN_ID.toString(), String.valueOf(nextId.getSpanId())); + request.setRequestProperty(Header.HTTP_PARENT_SPAN_ID.toString(), String.valueOf(nextId.getParentSpanId())); + + request.setRequestProperty(Header.HTTP_FLAGS.toString(), String.valueOf(nextId.getFlags())); + request.setRequestProperty(Header.HTTP_PARENT_APPLICATION_NAME.toString(), traceContext.getApplicationName()); + request.setRequestProperty(Header.HTTP_PARENT_APPLICATION_TYPE.toString(), Short.toString(traceContext.getServerTypeCode())); + + trace.recordServiceType(SERVICE_TYPE); + + final URL url = request.getURL(); + final String host = url.getHost(); + final int port = url.getPort(); + + // TODO How to represent protocol? + String endpoint = getEndpoint(host, port); + + // Don't record end point because it's same with destination id. + trace.recordDestinationId(endpoint); + trace.recordAttribute(AnnotationKey.HTTP_URL, url.toString()); + } + + private String getEndpoint(String host, int port) { + if (port < 0) { + return host; + } + StringBuilder sb = new StringBuilder(32); + sb.append(host); + sb.append(':'); + sb.append(port); + return sb.toString(); + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + // do not log result + logger.afterInterceptor(target, args); + } + + Trace trace = traceContext.currentTraceObject(); + if (trace == null) { + return; + } + + Object marker = trace.getTraceBlockAttachment(); + + if (marker != TRACE_BLOCK_BEGIN_MARKER) { + return; + } + + try { + trace.recordApi(descriptor); + trace.recordException(throwable); + + trace.markAfterTime(); + } finally { + trace.traceBlockEnd(); + } + } +} \ No newline at end of file diff --git a/plugins/jdk-http/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin b/plugins/jdk-http/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin new file mode 100644 index 000000000..685e09b42 --- /dev/null +++ b/plugins/jdk-http/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin @@ -0,0 +1 @@ +com.navercorp.pinpoint.plugin.jdk.http.JdkHttpPlugin \ No newline at end of file diff --git a/plugins/jdk-http/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.plugin.TypeProvider b/plugins/jdk-http/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.plugin.TypeProvider new file mode 100644 index 000000000..4acd8efa1 --- /dev/null +++ b/plugins/jdk-http/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.plugin.TypeProvider @@ -0,0 +1 @@ +com.navercorp.pinpoint.plugin.jdk.http.JdkHttpTypeProvider \ No newline at end of file diff --git a/plugins/pom.xml b/plugins/pom.xml index 450f950c3..3e8db9041 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -12,12 +12,23 @@ pom + jdk-http + redis servlet tomcat - redis + + com.navercorp.pinpoint + pinpoint-jdk-http-plugin + ${project.version} + + + com.navercorp.pinpoint + pinpoint-redis-plugin + ${project.version} + com.navercorp.pinpoint pinpoint-servlet-plugin @@ -28,10 +39,5 @@ pinpoint-tomcat-plugin ${project.version} - - com.navercorp.pinpoint - pinpoint-redis-plugin - ${project.version} - diff --git a/plugins/redis/src/main/java/com/navercorp/pinpoint/plugin/redis/RedisPlugin.java b/plugins/redis/src/main/java/com/navercorp/pinpoint/plugin/redis/RedisPlugin.java index aa391afdc..0f1483428 100644 --- a/plugins/redis/src/main/java/com/navercorp/pinpoint/plugin/redis/RedisPlugin.java +++ b/plugins/redis/src/main/java/com/navercorp/pinpoint/plugin/redis/RedisPlugin.java @@ -57,7 +57,7 @@ public class RedisPlugin implements ProfilerPlugin, RedisConstants { private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); @Override - public void setUp(ProfilerPluginSetupContext context) { + public void setup(ProfilerPluginSetupContext context) { final RedisPluginConfig config = new RedisPluginConfig(context.getConfig()); final boolean enabled = config.isEnabled(); final boolean pipelineEnabled = config.isPipelineEnabled(); @@ -86,8 +86,7 @@ public class RedisPlugin implements ProfilerPlugin, RedisConstants { } private ClassEditorBuilder addJedisExtendedClassEditor(ProfilerPluginSetupContext context, RedisPluginConfig config, final String targetClassName) { - final ClassEditorBuilder classEditorBuilder = context.newClassEditorBuilder(); - classEditorBuilder.target(targetClassName); + final ClassEditorBuilder classEditorBuilder = context.getClassEditorBuilder(targetClassName); final ConstructorEditorBuilder constructorEditorBuilderArg1 = classEditorBuilder.editConstructor(STRING); constructorEditorBuilderArg1.property(MethodEditorProperty.IGNORE_IF_NOT_EXIST); @@ -125,8 +124,7 @@ public class RedisPlugin implements ProfilerPlugin, RedisConstants { // Client private void addJedisClientClassEditor(ProfilerPluginSetupContext context, RedisPluginConfig config) { - final ClassEditorBuilder classEditorBuilder = context.newClassEditorBuilder(); - classEditorBuilder.target(JEDIS_CLIENT); + final ClassEditorBuilder classEditorBuilder = context.getClassEditorBuilder(JEDIS_CLIENT); classEditorBuilder.injectMetadata(METADATA_END_POINT); final ConstructorEditorBuilder constructorEditorBuilderArg1 = classEditorBuilder.editConstructor(STRING); @@ -161,8 +159,7 @@ public class RedisPlugin implements ProfilerPlugin, RedisConstants { } private ClassEditorBuilder addJedisPipelineBaseExtendedClassEditor(ProfilerPluginSetupContext context, RedisPluginConfig config, String targetClassName) { - final ClassEditorBuilder classEditorBuilder = context.newClassEditorBuilder(); - classEditorBuilder.target(targetClassName); + final ClassEditorBuilder classEditorBuilder = context.getClassEditorBuilder(targetClassName); final MethodEditorBuilder methodEditorBuilder = classEditorBuilder.editMethods(new NameBasedMethodFilter(JedisPipelineMethodNames.get())); methodEditorBuilder.exceptionHandler(new MethodEditorExceptionHandler() { diff --git a/plugins/redis/src/main/java/com/navercorp/pinpoint/plugin/redis/RedisTypeProvider.java b/plugins/redis/src/main/java/com/navercorp/pinpoint/plugin/redis/RedisTypeProvider.java index 799d9ae21..f22a9de02 100644 --- a/plugins/redis/src/main/java/com/navercorp/pinpoint/plugin/redis/RedisTypeProvider.java +++ b/plugins/redis/src/main/java/com/navercorp/pinpoint/plugin/redis/RedisTypeProvider.java @@ -21,7 +21,7 @@ import com.navercorp.pinpoint.common.plugin.TypeSetupContext; public class RedisTypeProvider implements TypeProvider, RedisConstants{ @Override - public void setUp(TypeSetupContext context) { + public void setup(TypeSetupContext context) { context.addType(REDIS); } } diff --git a/plugins/servlet/src/main/java/com/navercorp/pinpoint/plugin/servlet/ServletPlugin.java b/plugins/servlet/src/main/java/com/navercorp/pinpoint/plugin/servlet/ServletPlugin.java index 4da2a840b..7f8940f1d 100644 --- a/plugins/servlet/src/main/java/com/navercorp/pinpoint/plugin/servlet/ServletPlugin.java +++ b/plugins/servlet/src/main/java/com/navercorp/pinpoint/plugin/servlet/ServletPlugin.java @@ -26,13 +26,12 @@ import com.navercorp.pinpoint.bootstrap.plugin.editor.MethodEditorBuilder; public class ServletPlugin implements ProfilerPlugin { @Override - public void setUp(ProfilerPluginSetupContext context) { + public void setup(ProfilerPluginSetupContext context) { addHttpServletEditor(context); } private void addHttpServletEditor(ProfilerPluginSetupContext context) { - ClassEditorBuilder builder = context.newClassEditorBuilder(); - builder.target("javax.servlet.http.HttpServlet"); + ClassEditorBuilder builder = context.getClassEditorBuilder("javax.servlet.http.HttpServlet"); MethodEditorBuilder doGetBuilder = builder.editMethod("doGet", "javax.servlet.http.HttpServletRequest", "javax.servlet.http.HttpServletResponse"); doGetBuilder.injectInterceptor("com.navercorp.pinpoint.profiler.modifier.method.interceptor.MethodInterceptor", ServletConstants.SERVLET); diff --git a/plugins/servlet/src/main/java/com/navercorp/pinpoint/plugin/servlet/ServletTypeProvider.java b/plugins/servlet/src/main/java/com/navercorp/pinpoint/plugin/servlet/ServletTypeProvider.java index 31b0aa9b6..b3fa9a67b 100644 --- a/plugins/servlet/src/main/java/com/navercorp/pinpoint/plugin/servlet/ServletTypeProvider.java +++ b/plugins/servlet/src/main/java/com/navercorp/pinpoint/plugin/servlet/ServletTypeProvider.java @@ -24,7 +24,7 @@ import com.navercorp.pinpoint.common.plugin.TypeSetupContext; public class ServletTypeProvider implements TypeProvider { @Override - public void setUp(TypeSetupContext context) { + public void setup(TypeSetupContext context) { context.addType(ServletConstants.SERVLET); } diff --git a/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java b/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java index 5c26f8dd2..1a259223c 100644 --- a/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java +++ b/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatDetector.java @@ -14,7 +14,7 @@ */ package com.navercorp.pinpoint.plugin.tomcat; -import com.navercorp.pinpoint.bootstrap.plugin.ServerTypeDetector; +import com.navercorp.pinpoint.bootstrap.plugin.ApplicationTypeDetector; import com.navercorp.pinpoint.bootstrap.resolver.ConditionProvider; import com.navercorp.pinpoint.common.ServiceType; @@ -23,7 +23,7 @@ import com.navercorp.pinpoint.common.ServiceType; * @author HyunGil Jeong * */ -public class TomcatDetector implements ServerTypeDetector, TomcatConstants { +public class TomcatDetector implements ApplicationTypeDetector, TomcatConstants { private static final String REQUIRED_MAIN_CLASS = "org.apache.catalina.startup.Bootstrap"; diff --git a/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatPlugin.java b/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatPlugin.java index d1e9793ca..d25fae544 100644 --- a/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatPlugin.java +++ b/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatPlugin.java @@ -31,8 +31,8 @@ public class TomcatPlugin implements ProfilerPlugin { * @see com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin#setUp(com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginSetupContext) */ @Override - public void setUp(ProfilerPluginSetupContext context) { - context.addServerTypeDetector(new TomcatDetector()); + public void setup(ProfilerPluginSetupContext context) { + context.addApplicationTypeDetector(new TomcatDetector()); TomcatConfiguration config = new TomcatConfiguration(context.getConfig()); @@ -48,22 +48,19 @@ public class TomcatPlugin implements ProfilerPlugin { } private void addRequestFacadeEditor(ProfilerPluginSetupContext context) { - ClassEditorBuilder builder = context.newClassEditorBuilder(); - builder.target("org.apache.catalina.connector.RequestFacade"); + ClassEditorBuilder builder = context.getClassEditorBuilder("org.apache.catalina.connector.RequestFacade"); builder.weave("com.navercorp.pinpoint.plugin.tomcat.aspect.RequestFacadeAspect"); context.addClassEditor(builder.build()); } private void addStandardHostValveEditor(ProfilerPluginSetupContext context, TomcatConfiguration config) { - ClassEditorBuilder builder = context.newClassEditorBuilder(); - builder.target("org.apache.catalina.core.StandardHostValve"); + ClassEditorBuilder builder = context.getClassEditorBuilder("org.apache.catalina.core.StandardHostValve"); builder.injectInterceptor("com.navercorp.pinpoint.plugin.tomcat.interceptor.StandardHostValveInvokeInterceptor", config.getTomcatExcludeUrlFilter()); context.addClassEditor(builder.build()); } private void addStandardServiceEditor(ProfilerPluginSetupContext context) { - ClassEditorBuilder builder = context.newClassEditorBuilder(); - builder.target("org.apache.catalina.core.StandardService"); + ClassEditorBuilder builder = context.getClassEditorBuilder("org.apache.catalina.core.StandardService"); // Tomcat 6 MethodEditorBuilder startEditor = builder.editMethod("start"); @@ -79,8 +76,7 @@ public class TomcatPlugin implements ProfilerPlugin { } private void addTomcatConnectorEditor(ProfilerPluginSetupContext context) { - ClassEditorBuilder builder = context.newClassEditorBuilder(); - builder.target("org.apache.catalina.connector.Connector"); + ClassEditorBuilder builder = context.getClassEditorBuilder("org.apache.catalina.connector.Connector"); // Tomcat 6 MethodEditorBuilder initializeEditor = builder.editMethod("initialize"); @@ -96,8 +92,7 @@ public class TomcatPlugin implements ProfilerPlugin { } private void addWebappLoaderEditor(ProfilerPluginSetupContext context) { - ClassEditorBuilder builder = context.newClassEditorBuilder(); - builder.target("org.apache.catalina.loader.WebappLoader"); + ClassEditorBuilder builder = context.getClassEditorBuilder("org.apache.catalina.loader.WebappLoader"); // Tomcat 6 - org.apache.catalina.loader.WebappLoader.start() diff --git a/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatTypeProvider.java b/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatTypeProvider.java index 76ee8ab6f..8b9bcb924 100644 --- a/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatTypeProvider.java +++ b/plugins/tomcat/src/main/java/com/navercorp/pinpoint/plugin/tomcat/TomcatTypeProvider.java @@ -24,7 +24,7 @@ import com.navercorp.pinpoint.common.plugin.TypeSetupContext; public class TomcatTypeProvider implements TypeProvider, TomcatConstants { @Override - public void setUp(TypeSetupContext context) { + public void setup(TypeSetupContext context) { context.addType(TOMCAT); } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/DefaultAgent.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/DefaultAgent.java index 74c47a57d..bba1c6d09 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/DefaultAgent.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/DefaultAgent.java @@ -212,7 +212,7 @@ public class DefaultAgent implements Agent { logger.info("Loading plugin: {}", plugin.getClass().getName()); DefaultProfilerPluginContext context = new DefaultProfilerPluginContext(this); - plugin.setUp(context); + plugin.setup(context); pluginContexts.add(context); } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DefaultTrace.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DefaultTrace.java index 5ae481809..eeac88ca5 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DefaultTrace.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DefaultTrace.java @@ -16,7 +16,16 @@ package com.navercorp.pinpoint.profiler.context; -import com.navercorp.pinpoint.bootstrap.context.*; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.navercorp.pinpoint.bootstrap.context.AttributeScope; +import com.navercorp.pinpoint.bootstrap.context.Trace; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.context.TraceId; import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor; import com.navercorp.pinpoint.bootstrap.util.StringUtils; import com.navercorp.pinpoint.common.AnnotationKey; @@ -27,9 +36,6 @@ import com.navercorp.pinpoint.exception.PinpointException; import com.navercorp.pinpoint.profiler.context.storage.Storage; import com.navercorp.pinpoint.thrift.dto.TIntStringStringValue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * @author netspider @@ -52,6 +58,8 @@ public final class DefaultTrace implements Trace { private Storage storage; private final TraceContext traceContext; + + private final Map attributeMap = new HashMap(); // use for calculating depth of each Span. private int latestStackIndex = -1; @@ -547,4 +555,34 @@ public final class DefaultTrace implements Trace { public short getServiceType() { return currentStackFrame.getServiceType(); } + + @Override + public Object getAttribute(String key) { + return attributeMap.get(key); + } + + @Override + public Object setAttribute(String key, Object value) { + return attributeMap.put(key, value); + } + + @Override + public Object removeAttribute(String key) { + return attributeMap.remove(key); + } + + @Override + public Object setTraceBlockAttachment(Object attachment) { + return currentStackFrame.attachFrameObject(attachment); + } + + @Override + public Object getTraceBlockAttachment() { + return currentStackFrame.getFrameObject(); + } + + @Override + public Object removeTraceBlockAttachment() { + return currentStackFrame.detachFrameObject(); + } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DisableTrace.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DisableTrace.java index 089ebcd95..a01800b3a 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DisableTrace.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DisableTrace.java @@ -16,6 +16,9 @@ package com.navercorp.pinpoint.profiler.context; +import java.util.HashMap; +import java.util.Map; + import com.navercorp.pinpoint.bootstrap.context.Trace; import com.navercorp.pinpoint.bootstrap.context.TraceId; import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor; @@ -30,6 +33,8 @@ import com.navercorp.pinpoint.common.util.ParsingResult; public class DisableTrace implements Trace { public static final DisableTrace INSTANCE = new DisableTrace(); + + private final Map attributeMap = new HashMap(); private DisableTrace() { } @@ -204,4 +209,34 @@ public class DisableTrace implements Trace { public short getServiceType() { throw new UnsupportedOperationException(); } + + @Override + public Object getAttribute(String key) { + return attributeMap.get(key); + } + + @Override + public Object setAttribute(String key, Object value) { + return attributeMap.put(key, value); + } + + @Override + public Object removeAttribute(String key) { + return attributeMap.remove(key); + } + + @Override + public Object setTraceBlockAttachment(Object attachment) { + throw new UnsupportedOperationException(); + } + + @Override + public Object getTraceBlockAttachment() { + throw new UnsupportedOperationException(); + } + + @Override + public Object removeTraceBlockAttachment() { + throw new UnsupportedOperationException(); + } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/MetricTrace.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/MetricTrace.java index 1d3d0f699..ec57acfa3 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/MetricTrace.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/MetricTrace.java @@ -16,6 +16,12 @@ package com.navercorp.pinpoint.profiler.context; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.navercorp.pinpoint.bootstrap.context.Trace; import com.navercorp.pinpoint.bootstrap.context.TraceContext; import com.navercorp.pinpoint.bootstrap.context.TraceId; @@ -26,9 +32,6 @@ import com.navercorp.pinpoint.common.util.DefaultParsingResult; import com.navercorp.pinpoint.common.util.ParsingResult; import com.navercorp.pinpoint.exception.PinpointException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * @author emeroad */ @@ -37,7 +40,7 @@ public class MetricTrace implements Trace { private static final Logger logger = LoggerFactory.getLogger(MetricTrace.class.getName()); private static final boolean isDebug = logger.isDebugEnabled(); private static final boolean isTrace = logger.isTraceEnabled(); - + private static final int EXCEPTION_MARK = -1; private static final ParsingResult PARSING_RESULT = new DefaultParsingResult("", new StringBuilder()); @@ -50,6 +53,8 @@ public class MetricTrace implements Trace { private final TraceContext traceContext; + private final Map attributeMap = new HashMap(); + // use for calculating depth of each Span. private int latestStackIndex = -1; private StackFrame currentStackFrame; @@ -369,4 +374,34 @@ public class MetricTrace implements Trace { public short getServiceType() { return currentStackFrame.getServiceType(); } + + @Override + public Object getAttribute(String key) { + return attributeMap.get(key); + } + + @Override + public Object setAttribute(String key, Object value) { + return attributeMap.put(key, value); + } + + @Override + public Object removeAttribute(String key) { + return attributeMap.remove(key); + } + + @Override + public Object setTraceBlockAttachment(Object attachment) { + return currentStackFrame.attachFrameObject(attachment); + } + + @Override + public Object getTraceBlockAttachment() { + return currentStackFrame.getFrameObject(); + } + + @Override + public Object removeTraceBlockAttachment() { + return currentStackFrame.detachFrameObject(); + } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/RootStackFrame.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/RootStackFrame.java index 3764254c7..824a8de0d 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/RootStackFrame.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/RootStackFrame.java @@ -110,8 +110,10 @@ public class RootStackFrame implements StackFrame { } @Override - public void attachFrameObject(Object frameObject) { + public Object attachFrameObject(Object frameObject) { + Object copy = this.frameObject; this.frameObject = frameObject; + return copy; } @Override diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/SpanEventStackFrame.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/SpanEventStackFrame.java index 72b2a415d..637e43511 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/SpanEventStackFrame.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/SpanEventStackFrame.java @@ -114,8 +114,10 @@ public class SpanEventStackFrame implements StackFrame { } @Override - public void attachFrameObject(Object frameObject) { + public Object attachFrameObject(Object frameObject) { + Object copy = this.frameObject; this.frameObject = frameObject; + return copy; } @Override diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/StackFrame.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/StackFrame.java index 8de91731a..48d654107 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/StackFrame.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/StackFrame.java @@ -50,7 +50,7 @@ public interface StackFrame { short getServiceType(); - void attachFrameObject(Object frameObject); + Object attachFrameObject(Object frameObject); Object getFrameObject(); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClass.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClass.java index 4737b256d..3264c063e 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClass.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClass.java @@ -974,14 +974,49 @@ public class JavaAssistClass implements InstrumentClass { } try { - CtMethod getterMethod = CtNewMethod.make("public " + getter.getReturnType().getName() + " " + getter.getName() + "() { return " + fieldName + "; }", ctClass); + CtField field = ctClass.getField(fieldName); + String expression; + + if (field.getType().isPrimitive()) { + String fieldType = field.getType().getName(); + String wrapperType = getWrapperClassName(fieldType); + expression = wrapperType + ".valueOf(" + fieldName + ")"; + } else { + expression = fieldName; + } + + CtMethod getterMethod = CtNewMethod.make("public " + getter.getReturnType().getName() + " " + getter.getName() + "() { return " + expression + "; }", ctClass); ctClass.addMethod(getterMethod); CtClass ctInterface = instrumentor.getClass(interfaceType.getClassLoader(), interfaceType.getName()); ctClass.addInterface(ctInterface); + } catch (NotFoundException ex) { + throw new InstrumentException("Failed to add getter. No such field: " + fieldName, ex); } catch (Exception e) { // Cannot happen. Reaching here means a bug. throw new InstrumentException("Fail to add getter: " + interfaceType.getName(), e); } } + + private String getWrapperClassName(String primitiveType) { + if ("boolean".equals(primitiveType)) { + return "java.lang.Boolean"; + } else if ("byte".equals(primitiveType)) { + return "java.lang.Byte"; + } else if ("short".equals(primitiveType)) { + return "java.lang.Short"; + } else if ("int".equals(primitiveType)) { + return "java.lang.Integer"; + } else if ("long".equals(primitiveType)) { + return "java.lang.Long"; + } else if ("float".equals(primitiveType)) { + return "java.lang.Float"; + } else if ("double".equals(primitiveType)) { + return "java.lang.Double"; + } else if ("void".equals(primitiveType)) { + return "java.lang.Void"; + } + + throw new IllegalArgumentException(primitiveType); + } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java index 71d02eae9..2aec8f31f 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java @@ -138,10 +138,6 @@ public class DefaultModifierRegistry implements ModifierRegistry { addModifier(new DefaultHttpMethodRetryHandlerModifier(byteCodeInstrumentor, agent)); } - // JDK HTTPUrlConnector - HttpURLConnectionModifier httpURLConnectionModifier = new HttpURLConnectionModifier(byteCodeInstrumentor, agent); - addModifier(httpURLConnectionModifier); - // ning async http client addModifier(new AsyncHttpClientModifier(byteCodeInstrumentor, agent)); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/interceptor/ConnectMethodInterceptor.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/interceptor/ConnectMethodInterceptor.java index f7f461cdb..447c1812a 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/interceptor/ConnectMethodInterceptor.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/connector/jdkhttpconnector/interceptor/ConnectMethodInterceptor.java @@ -85,7 +85,7 @@ public class ConnectMethodInterceptor implements SimpleAroundInterceptor, ByteCo request.setRequestProperty(Header.HTTP_PARENT_APPLICATION_TYPE.toString(), Short.toString(traceContext.getServerTypeCode())); } - trace.recordServiceType(ServiceType.JDK_HTTPURLCONNECTOR); +// trace.recordServiceType(ServiceType.JDK_HTTPURLCONNECTOR); final URL url = request.getURL(); final String host = url.getHost(); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/DefaultProfilerPluginContext.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/DefaultProfilerPluginContext.java index dcbb67ba6..4afface7b 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/DefaultProfilerPluginContext.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/DefaultProfilerPluginContext.java @@ -28,9 +28,9 @@ import com.navercorp.pinpoint.bootstrap.MetadataAccessor; import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig; import com.navercorp.pinpoint.bootstrap.context.TraceContext; import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor; +import com.navercorp.pinpoint.bootstrap.plugin.ApplicationTypeDetector; import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginContext; import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginSetupContext; -import com.navercorp.pinpoint.bootstrap.plugin.ServerTypeDetector; import com.navercorp.pinpoint.bootstrap.plugin.editor.ClassEditor; import com.navercorp.pinpoint.bootstrap.plugin.editor.ClassEditorBuilder; import com.navercorp.pinpoint.profiler.DefaultAgent; @@ -39,7 +39,7 @@ import com.navercorp.pinpoint.profiler.plugin.editor.DefaultClassEditorBuilder; public class DefaultProfilerPluginContext implements ProfilerPluginSetupContext, ProfilerPluginContext { private final DefaultAgent agent; - private final List serverTypeDetectors = new ArrayList(); + private final List serverTypeDetectors = new ArrayList(); private final List classEditors = new ArrayList(); private final ConcurrentMap attributeMap = new ConcurrentHashMap(); @@ -54,8 +54,8 @@ public class DefaultProfilerPluginContext implements ProfilerPluginSetupContext, } @Override - public ClassEditorBuilder newClassEditorBuilder() { - return new DefaultClassEditorBuilder(this); + public ClassEditorBuilder getClassEditorBuilder(String targetClassName) { + return new DefaultClassEditorBuilder(this, targetClassName); } @Override @@ -137,8 +137,8 @@ public class DefaultProfilerPluginContext implements ProfilerPluginSetupContext, } @Override - public void addServerTypeDetector(ServerTypeDetector... detectors) { - for (ServerTypeDetector detector : detectors) { + public void addApplicationTypeDetector(ApplicationTypeDetector... detectors) { + for (ApplicationTypeDetector detector : detectors) { serverTypeDetectors.add(detector); } } @@ -147,7 +147,7 @@ public class DefaultProfilerPluginContext implements ProfilerPluginSetupContext, return classEditors; } - public List getServerTypeDetectors() { + public List getApplicationTypeDetectors() { return serverTypeDetectors; } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/PluginClassLoaderFactory.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/PluginClassLoaderFactory.java index 5d470da0b..096452a2c 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/PluginClassLoaderFactory.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/PluginClassLoaderFactory.java @@ -22,6 +22,7 @@ import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.Logger; @@ -35,12 +36,22 @@ public class PluginClassLoaderFactory { private final URL[] pluginJars; private final ConcurrentHashMap cache = new ConcurrentHashMap(); + private final AtomicReference forBootstrapClassLoader = new AtomicReference(); public PluginClassLoaderFactory(URL[] pluginJars) { this.pluginJars = pluginJars; } - public ClassLoader get(ClassLoader loader) { + public ClassLoader get(ClassLoader loader) { + if (loader == null) { + // boot class loader + return getForBootstrap(); + } else { + return getForPlain(loader); + } + } + + private ClassLoader getForPlain(ClassLoader loader) { final ClassLoader forPlugin = cache.get(loader); if (forPlugin != null) { return forPlugin; @@ -50,12 +61,32 @@ public class PluginClassLoaderFactory { final ClassLoader before = cache.putIfAbsent(loader, newInstance); if (before == null) { return newInstance; - } - else { + } else { close (newInstance); return before; } } + + private ClassLoader getForBootstrap() { + final ClassLoader forPlugin = forBootstrapClassLoader.get(); + + if (forPlugin != null) { + return forPlugin; + } + + // Strictly, should pass null as parent class loader. + // But if so, All the types used by interceptors have to be loaded by bootstrap class loader. + // So we use system class loader as parent. + final ClassLoader newInstance = createPluginClassLoader(pluginJars, ClassLoader.getSystemClassLoader()); + boolean success = forBootstrapClassLoader.compareAndSet(null, newInstance); + + if (success) { + return newInstance; + } else { + close (newInstance); + return forBootstrapClassLoader.get(); + } + } private PluginClassLoader createPluginClassLoader(final URL[] urls, final ClassLoader parent) { if (SECURITY_MANAGER != null) { diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/ConditionalClassEditor.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/ConditionalClassRecipe.java similarity index 60% rename from profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/ConditionalClassEditor.java rename to profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/ConditionalClassRecipe.java index e1b4e7ba9..2654fc12f 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/ConditionalClassEditor.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/ConditionalClassRecipe.java @@ -17,29 +17,24 @@ package com.navercorp.pinpoint.profiler.plugin.editor; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; +import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginContext; import com.navercorp.pinpoint.bootstrap.plugin.editor.ClassCondition; -import com.navercorp.pinpoint.bootstrap.plugin.editor.DedicatedClassEditor; -public class ConditionalClassEditor implements DedicatedClassEditor { +public class ConditionalClassRecipe implements ClassRecipe { + private final ProfilerPluginContext context; private final ClassCondition condition; - private final DedicatedClassEditor delegate; + private final ClassRecipe delegate; - public ConditionalClassEditor(ClassCondition condition, DedicatedClassEditor delegate) { + public ConditionalClassRecipe(ProfilerPluginContext context, ClassCondition condition, ClassRecipe delegate) { + this.context = context; this.condition = condition; this.delegate = delegate; } - + @Override - public byte[] edit(ClassLoader classLoader, InstrumentClass target) { - if (condition.check(classLoader, target)) { - return delegate.edit(classLoader, target); + public void edit(ClassLoader classLoader, InstrumentClass target) throws Exception { + if (condition.check(context, classLoader, target)) { + delegate.edit(classLoader, target); } - - return null; - } - - @Override - public String getTargetClassName() { - return delegate.getTargetClassName(); } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/ConditionalMethodEditor.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/ConditionalMethodEditor.java index 53f61d2a7..72c3287c9 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/ConditionalMethodEditor.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/ConditionalMethodEditor.java @@ -17,20 +17,23 @@ package com.navercorp.pinpoint.profiler.plugin.editor; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; +import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginContext; import com.navercorp.pinpoint.bootstrap.plugin.editor.ClassCondition; public class ConditionalMethodEditor implements MethodEditor { + private final ProfilerPluginContext context; private final ClassCondition condition; private final MethodEditor delegate; - public ConditionalMethodEditor(ClassCondition condition, MethodEditor delegate) { + public ConditionalMethodEditor(ProfilerPluginContext context, ClassCondition condition, MethodEditor delegate) { + this.context = context; this.condition = condition; this.delegate = delegate; } @Override public void edit(ClassLoader classLoader, InstrumentClass target) throws Exception { - if (condition.check(classLoader, target)) { + if (condition.check(context, classLoader, target)) { delegate.edit(classLoader, target); } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/DefaultClassEditorBuilder.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/DefaultClassEditorBuilder.java index fd36f8d26..269345d1c 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/DefaultClassEditorBuilder.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/DefaultClassEditorBuilder.java @@ -26,6 +26,8 @@ import com.navercorp.pinpoint.bootstrap.MetadataAccessor; import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter; import com.navercorp.pinpoint.bootstrap.plugin.editor.ClassCondition; import com.navercorp.pinpoint.bootstrap.plugin.editor.ClassEditorBuilder; +import com.navercorp.pinpoint.bootstrap.plugin.editor.ConditionalClassEditorBuilder; +import com.navercorp.pinpoint.bootstrap.plugin.editor.ConditionalClassEditorSetup; import com.navercorp.pinpoint.bootstrap.plugin.editor.ConstructorEditorBuilder; import com.navercorp.pinpoint.bootstrap.plugin.editor.DedicatedClassEditor; import com.navercorp.pinpoint.bootstrap.plugin.editor.MethodEditorBuilder; @@ -38,31 +40,34 @@ import com.navercorp.pinpoint.profiler.plugin.MetadataInjector; import com.navercorp.pinpoint.profiler.plugin.interceptor.AnnotatedInterceptorInjector; import com.navercorp.pinpoint.profiler.plugin.interceptor.TargetAnnotatedInterceptorInjector; -public class DefaultClassEditorBuilder implements ClassEditorBuilder { +public class DefaultClassEditorBuilder implements ClassEditorBuilder, ConditionalClassEditorBuilder, RecipeBuilder { private final DefaultProfilerPluginContext pluginContext; private final List recipes = new ArrayList(); private final List> recipeBuilders = new ArrayList>(); - private String targetClassName; - private ClassCondition condition; + private final ClassCondition condition; + private final String targetClassName; - public DefaultClassEditorBuilder(DefaultProfilerPluginContext pluginContext) { - this.pluginContext = pluginContext; - } - - @Override - public void target(String targetClassName) { - this.targetClassName = targetClassName; + public DefaultClassEditorBuilder(DefaultProfilerPluginContext pluginContext, String targetClassName) { + this(pluginContext, targetClassName, null); } - @Override - public void condition(ClassCondition condition) { + private DefaultClassEditorBuilder(DefaultProfilerPluginContext pluginContext, String targetClassName, ClassCondition condition) { + this.pluginContext = pluginContext; + this.targetClassName = targetClassName; this.condition = condition; } + + @Override + public void conditional(ClassCondition condition, ConditionalClassEditorSetup describer) { + DefaultClassEditorBuilder conditional = new DefaultClassEditorBuilder(pluginContext, targetClassName, condition); + describer.setup(conditional); + recipeBuilders.add(conditional); + } @Override - public void injectFieldSnooper(String fieldName) { + public void injectFieldAccessor(String fieldName) { FieldAccessor snooper = pluginContext.allocateFieldSnooper(fieldName); recipes.add(new FieldSnooperInjector(snooper, fieldName)); } @@ -113,25 +118,14 @@ public class DefaultClassEditorBuilder implements ClassEditorBuilder { @Override public DedicatedClassEditor build() { ClassRecipe recipe = buildClassRecipe(); - DedicatedClassEditor editor = buildClassEditor(recipe); - - return editor; - } - - private DedicatedClassEditor buildClassEditor(ClassRecipe recipe) { - DedicatedClassEditor editor = new DefaultDedicatedClassEditor(targetClassName, recipe); - - if (condition != null) { - editor = new ConditionalClassEditor(condition, editor); - } - return editor; + return new DefaultDedicatedClassEditor(targetClassName, recipe); } private ClassRecipe buildClassRecipe() { List recipes = new ArrayList(this.recipes); for (RecipeBuilder builder : recipeBuilders) { - recipes.add(builder.build()); + recipes.add(builder.buildRecipe()); } if (recipes.isEmpty()) { @@ -142,10 +136,19 @@ public class DefaultClassEditorBuilder implements ClassEditorBuilder { return recipe; } - private interface RecipeBuilder { - public T build(); + @Override + public ClassRecipe buildRecipe() { + if (condition == null) { + throw new IllegalStateException(); + } + + ClassRecipe recipe = buildClassRecipe(); + return new ConditionalClassRecipe(pluginContext, condition, recipe); } + + + private class TargetAnnotatedInterceptorInjectorBuilder implements RecipeBuilder { private final String interceptorClassName; private final Object[] constructorArguments; @@ -156,7 +159,7 @@ public class DefaultClassEditorBuilder implements ClassEditorBuilder { } @Override - public ClassRecipe build() { + public ClassRecipe buildRecipe() { return new TargetAnnotatedInterceptorInjector(pluginContext, interceptorClassName, constructorArguments); } } @@ -171,7 +174,7 @@ public class DefaultClassEditorBuilder implements ClassEditorBuilder { } @Override - public MethodRecipe build() { + public MethodRecipe buildRecipe() { return new AnnotatedInterceptorInjector(pluginContext, interceptorClassName, constructorArguments); } } @@ -182,7 +185,6 @@ public class DefaultClassEditorBuilder implements ClassEditorBuilder { private final MethodFilter filter; private final List> recipeBuilders = new ArrayList>(); private final EnumSet properties = EnumSet.noneOf(MethodEditorProperty.class); - private ClassCondition condition; private MethodEditorExceptionHandler exceptionHandler; private DefaultMethodEditorBuilder(String... parameterTypeNames) { @@ -203,11 +205,6 @@ public class DefaultClassEditorBuilder implements ClassEditorBuilder { this.filter = filter; } - @Override - public void condition(ClassCondition condition) { - this.condition = condition; - } - @Override public void property(MethodEditorProperty... properties) { this.properties.addAll(Arrays.asList(properties)); @@ -223,7 +220,8 @@ public class DefaultClassEditorBuilder implements ClassEditorBuilder { this.exceptionHandler = handler; } - public MethodEditor build() { + @Override + public MethodEditor buildRecipe() { List recipes = buildMethodRecipe(); MethodEditor editor = buildMethodEditor(recipes); @@ -240,10 +238,6 @@ public class DefaultClassEditorBuilder implements ClassEditorBuilder { editor = new ConstructorEditor(parameterTypeNames, recipes, exceptionHandler, properties.contains(MethodEditorProperty.IGNORE_IF_NOT_EXIST)); } - if (condition != null) { - editor = new ConditionalMethodEditor(condition, editor); - } - return editor; } @@ -256,7 +250,7 @@ public class DefaultClassEditorBuilder implements ClassEditorBuilder { List recipes = new ArrayList(recipeBuilders.size()); for (RecipeBuilder builder : recipeBuilders) { - recipes.add(builder.build()); + recipes.add(builder.buildRecipe()); } return recipes; diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/RecipeBuilder.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/RecipeBuilder.java new file mode 100644 index 000000000..4ab6e029e --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/editor/RecipeBuilder.java @@ -0,0 +1,23 @@ +/** + * Copyright 2014 NAVER Corp. + * Licensed 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 com.navercorp.pinpoint.profiler.plugin.editor; + +/** + * @author Jongho Moon + * + */ +interface RecipeBuilder { + T buildRecipe(); +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java index 6bc11379d..7fe34f496 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ApplicationServerTypeResolver.java @@ -24,7 +24,7 @@ import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.navercorp.pinpoint.bootstrap.plugin.ServerTypeDetector; +import com.navercorp.pinpoint.bootstrap.plugin.ApplicationTypeDetector; import com.navercorp.pinpoint.bootstrap.resolver.ApplicationServerTypePluginResolver; import com.navercorp.pinpoint.common.ServiceType; import com.navercorp.pinpoint.profiler.plugin.DefaultProfilerPluginContext; @@ -40,7 +40,7 @@ public class ApplicationServerTypeResolver { private final ServiceType defaultType; private final ApplicationServerTypePluginResolver resolver; - private final List detectors = new ArrayList(); + private final List detectors = new ArrayList(); public ApplicationServerTypeResolver(List plugins, ServiceType defaultType, List orderedDetectors) { if (isValidApplicationServerType(defaultType)) { @@ -48,7 +48,7 @@ public class ApplicationServerTypeResolver { } else { this.defaultType = ServiceType.UNDEFINED; } - Map registeredDetectors = getRegisteredServerTypeDetectors(plugins); + Map registeredDetectors = getRegisteredServerTypeDetectors(plugins); for (String orderedDetector : orderedDetectors) { if (registeredDetectors.containsKey(orderedDetector)) { this.detectors.add(registeredDetectors.remove(orderedDetector)); @@ -58,10 +58,10 @@ public class ApplicationServerTypeResolver { this.resolver = new ApplicationServerTypePluginResolver(this.detectors); } - private Map getRegisteredServerTypeDetectors(List plugins) { - Map registeredDetectors = new HashMap(); + private Map getRegisteredServerTypeDetectors(List plugins) { + Map registeredDetectors = new HashMap(); for (DefaultProfilerPluginContext context : plugins) { - for (ServerTypeDetector detector : context.getServerTypeDetectors()) { + for (ApplicationTypeDetector detector : context.getApplicationTypeDetectors()) { registeredDetectors.put(detector.getClass().getName(), detector); } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/test/PluginTestAgent.java b/profiler/src/main/java/com/navercorp/pinpoint/test/PluginTestAgent.java index d5a8c62d9..f0b819d8d 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/test/PluginTestAgent.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/test/PluginTestAgent.java @@ -25,8 +25,6 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; -import com.navercorp.pinpoint.common.service.AnnotationKeyRegistryService; -import com.navercorp.pinpoint.common.service.DefaultAnnotationKeyRegistryService; import org.apache.thrift.TBase; import com.google.common.base.Objects; @@ -40,6 +38,8 @@ import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier; import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifierHolder; import com.navercorp.pinpoint.common.AnnotationKey; import com.navercorp.pinpoint.common.ServiceType; +import com.navercorp.pinpoint.common.service.AnnotationKeyRegistryService; +import com.navercorp.pinpoint.common.service.DefaultAnnotationKeyRegistryService; import com.navercorp.pinpoint.common.service.ServiceTypeRegistryService; import com.navercorp.pinpoint.profiler.DefaultAgent; import com.navercorp.pinpoint.profiler.context.Span; @@ -107,7 +107,7 @@ public class PluginTestAgent extends DefaultAgent implements PluginTestVerifier ServiceType expectedType = findServiceType(serviceTypeName); ServiceType actualType = getAgentInformation().getServerType(); - if (expectedType != actualType) { + if (!expectedType.equals(actualType)) { throw new AssertionError("Expected server type: " + expectedType.getName() + "[" + expectedType.getCode() + "] but was " + actualType + "[" + actualType.getCode() + "]"); } } @@ -195,7 +195,7 @@ public class PluginTestAgent extends DefaultAgent implements PluginTestVerifier public void verifySpanEvent(String serviceTypeName, Method method, String rpc, String endPoint, String destinationId, ExpectedAnnotation... annotations) { ServiceType serviceType = findServiceType(serviceTypeName); int apiId = findApiId(method); - Expected expected = new Expected(Span.class, serviceType, apiId, rpc, endPoint, null, destinationId, annotations); + Expected expected = new Expected(SpanEvent.class, serviceType, apiId, rpc, endPoint, null, destinationId, annotations); verifySpan(expected); } diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClassTest.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClassTest.java index 03e629cb1..02d614b2d 100644 --- a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClassTest.java +++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistClassTest.java @@ -453,7 +453,8 @@ public class JavaAssistClassTest { public void testAddGetter() throws Exception { final TestClassLoader loader = getTestClassLoader(); final String testClassObject = "com.navercorp.pinpoint.profiler.interceptor.bci.TestObject3"; - final FieldAccessor snooper = FieldAccessor.get(0); + final FieldAccessor accessor0 = FieldAccessor.get(0); + final FieldAccessor accessor1 = FieldAccessor.get(1); final TestModifier testModifier = new TestModifier(loader.getInstrumentor(), loader.getProfilerConfig()) { @Override @@ -461,7 +462,8 @@ public class JavaAssistClassTest { try { logger.info("modify cl:{}", classLoader); InstrumentClass aClass = byteCodeInstrumentor.getClass(classLoader, testClassObject, classFileBuffer); - aClass.addGetter(snooper.getType(), "value"); + aClass.addGetter(accessor0.getType(), "value"); + aClass.addGetter(accessor1.getType(), "intValue"); return aClass.toBytecode(); } catch (InstrumentException e) { @@ -475,15 +477,21 @@ public class JavaAssistClassTest { loader.initialize(); Object testObject = loader.loadClass(testClassObject).newInstance(); - Assert.assertTrue(snooper.isApplicable(testObject)); + Assert.assertTrue(accessor0.isApplicable(testObject)); + Assert.assertTrue(accessor1.isApplicable(testObject)); String value = "hehe"; + int intValue = 99; Method method = testObject.getClass().getMethod("setValue", String.class); method.invoke(testObject, value); - Assert.assertEquals(value, snooper.get(testObject)); + Assert.assertEquals(value, accessor0.get(testObject)); + Method setIntValue = testObject.getClass().getMethod("setIntValue", int.class); + setIntValue.invoke(testObject, intValue); + + Assert.assertEquals(intValue, accessor1.get(testObject)); } } diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject3.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject3.java index f4c77c4b7..8ee9b70e3 100644 --- a/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject3.java +++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/interceptor/bci/TestObject3.java @@ -20,10 +20,15 @@ package com.navercorp.pinpoint.profiler.interceptor.bci; */ public class TestObject3 { private String value; + private int intValue; public void setValue(String value) { this.value = value; } + + public void setIntValue(int value) { + this.intValue = value; + } @Override public String toString() { diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/DefaultClassEditorBuilderTest.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/DefaultClassEditorBuilderTest.java index bf6adb921..146d572cb 100644 --- a/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/DefaultClassEditorBuilderTest.java +++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/DefaultClassEditorBuilderTest.java @@ -63,9 +63,9 @@ public class DefaultClassEditorBuilderTest { when(aClass.addInterceptor(eq(methodName), eq(parameterTypeNames), isA(Interceptor.class))).thenReturn(0); DefaultProfilerPluginContext context = new DefaultProfilerPluginContext(agent); - DefaultClassEditorBuilder builder = new DefaultClassEditorBuilder(context); + DefaultClassEditorBuilder builder = new DefaultClassEditorBuilder(context, "TargetClass"); builder.injectMetadata("a", "java.util.HashMap"); - builder.injectFieldSnooper("someField"); + builder.injectFieldAccessor("someField"); MethodEditorBuilder ib = builder.editMethod(methodName, parameterTypeNames); ib.injectInterceptor("com.navercorp.pinpoint.profiler.plugin.TestInterceptor", "provided"); diff --git a/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestException.java b/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestException.java index b3c4b2f3c..b3957aff9 100644 --- a/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestException.java +++ b/test/src/main/java/com/navercorp/pinpoint/test/plugin/PinpointPluginTestException.java @@ -19,9 +19,27 @@ package com.navercorp.pinpoint.test.plugin; * */ @SuppressWarnings("serial") -public class PinpointPluginTestException extends Exception { +public class PinpointPluginTestException extends RuntimeException { public PinpointPluginTestException(String message, StackTraceElement[] stackTrace) { super(message); setStackTrace(stackTrace); } + + public PinpointPluginTestException() { + super(); + } + + public PinpointPluginTestException(String message, Throwable cause) { + super(message, cause); + } + + public PinpointPluginTestException(String message) { + super(message); + } + + public PinpointPluginTestException(Throwable cause) { + super(cause); + } + + }