Support op group name in agent config core. (#3299)
* Support op group name in agent config core. * Provide core API for operation name grouping, rest template plugin update, and doc update. * Fix doc * Fix test case. * Fix missing changes. * add shuyun to powered-by.md (#3341) * add shuyun to powered-by.md * update powered-by.md * Remove static method.
This commit is contained in:
parent
1cc4a517c2
commit
a3241f0a59
|
|
@ -23,12 +23,12 @@ import java.lang.reflect.Field;
|
|||
import java.lang.reflect.Modifier;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Init a class's static fields by a {@link Properties},
|
||||
* including static fields and static inner classes.
|
||||
* Init a class's static fields by a {@link Properties}, including static fields and static inner classes.
|
||||
* <p>
|
||||
* Created by wusheng on 2017/1/9.
|
||||
*/
|
||||
|
|
@ -44,21 +44,39 @@ public class ConfigInitializer {
|
|||
for (Field field : recentConfigType.getFields()) {
|
||||
if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
|
||||
String configKey = (parentDesc + "." + field.getName()).toLowerCase();
|
||||
String value = properties.getProperty(configKey);
|
||||
if (value != null) {
|
||||
Class<?> type = field.getType();
|
||||
if (type.equals(int.class))
|
||||
field.set(null, Integer.valueOf(value));
|
||||
else if (type.equals(String.class))
|
||||
field.set(null, value);
|
||||
else if (type.equals(long.class))
|
||||
field.set(null, Long.valueOf(value));
|
||||
else if (type.equals(boolean.class))
|
||||
field.set(null, Boolean.valueOf(value));
|
||||
else if (type.equals(List.class))
|
||||
field.set(null, convert2List(value));
|
||||
else if (type.isEnum())
|
||||
field.set(null, Enum.valueOf((Class<Enum>)type, value.toUpperCase()));
|
||||
/**
|
||||
* Map config format is, config_key[map_key]=map_value
|
||||
* Such as plugin.opgroup.resttemplate.rule[abc]=/url/path
|
||||
*/
|
||||
if (field.getType().equals(Map.class)) {
|
||||
Map map = (Map)field.get(null);
|
||||
for (Object key : properties.keySet()) {
|
||||
String stringKey = key.toString();
|
||||
if (stringKey.startsWith(configKey + "[") && stringKey.endsWith("]")) {
|
||||
String itemKey = stringKey.substring(configKey.length() + 1, stringKey.length() - 1);
|
||||
map.put(itemKey, properties.getProperty(stringKey));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Others typical field type
|
||||
*/
|
||||
String value = properties.getProperty(configKey);
|
||||
if (value != null) {
|
||||
Class<?> type = field.getType();
|
||||
if (type.equals(int.class))
|
||||
field.set(null, Integer.valueOf(value));
|
||||
else if (type.equals(String.class))
|
||||
field.set(null, value);
|
||||
else if (type.equals(long.class))
|
||||
field.set(null, Long.valueOf(value));
|
||||
else if (type.equals(boolean.class))
|
||||
field.set(null, Boolean.valueOf(value));
|
||||
else if (type.equals(List.class))
|
||||
field.set(null, convert2List(value));
|
||||
else if (type.isEnum())
|
||||
field.set(null, Enum.valueOf((Class<Enum>)type, value.toUpperCase()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,14 +19,13 @@
|
|||
|
||||
package org.apache.skywalking.apm.agent.core.conf;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
|
||||
import org.apache.skywalking.apm.agent.core.logging.core.LogLevel;
|
||||
import org.apache.skywalking.apm.agent.core.logging.core.LogOutput;
|
||||
import org.apache.skywalking.apm.agent.core.logging.core.WriterFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is the core config in sniffer agent.
|
||||
*
|
||||
|
|
@ -41,14 +40,14 @@ public class Config {
|
|||
public static String NAMESPACE = "";
|
||||
|
||||
/**
|
||||
* Service name is showed in skywalking-ui. Suggestion: set a unique name for each service,
|
||||
* service instance nodes share the same code
|
||||
* Service name is showed in skywalking-ui. Suggestion: set a unique name for each service, service instance
|
||||
* nodes share the same code
|
||||
*/
|
||||
public static String SERVICE_NAME = "";
|
||||
|
||||
/**
|
||||
* Authentication active is based on backend setting, see application.yml for more details.
|
||||
* For most scenarios, this needs backend extensions, only basic match auth provided in default implementation.
|
||||
* Authentication active is based on backend setting, see application.yml for more details. For most scenarios,
|
||||
* this needs backend extensions, only basic match auth provided in default implementation.
|
||||
*/
|
||||
public static String AUTHENTICATION = "";
|
||||
|
||||
|
|
@ -70,8 +69,8 @@ public class Config {
|
|||
public static int SPAN_LIMIT_PER_SEGMENT = 300;
|
||||
|
||||
/**
|
||||
* If true, skywalking agent will save all instrumented classes files in `/debugging` folder.
|
||||
* Skywalking team may ask for these files in order to resolve compatible problem.
|
||||
* If true, skywalking agent will save all instrumented classes files in `/debugging` folder. Skywalking team
|
||||
* may ask for these files in order to resolve compatible problem.
|
||||
*/
|
||||
public static boolean IS_OPEN_DEBUGGING_CLASS = false;
|
||||
|
||||
|
|
@ -96,16 +95,14 @@ public class Config {
|
|||
public static int CAUSE_EXCEPTION_DEPTH = 5;
|
||||
|
||||
/**
|
||||
* How long should the agent wait (in minute)
|
||||
* before re-registering to the OAP server
|
||||
* after receiving reset command
|
||||
* How long should the agent wait (in minute) before re-registering to the OAP server after receiving reset
|
||||
* command
|
||||
*/
|
||||
public static int COOL_DOWN_THRESHOLD = 10;
|
||||
|
||||
/**
|
||||
* Force reconnection period of grpc, based on grpc_channel_check_interval.
|
||||
* If count of check grpc channel status more than this number.
|
||||
* The channel check will call channel.getState(true) to requestConnection.
|
||||
* Force reconnection period of grpc, based on grpc_channel_check_interval. If count of check grpc channel
|
||||
* status more than this number. The channel check will call channel.getState(true) to requestConnection.
|
||||
*/
|
||||
public static long FORCE_RECONNECTION_PERIOD = 1;
|
||||
}
|
||||
|
|
@ -177,19 +174,13 @@ public class Config {
|
|||
public static LogOutput OUTPUT = LogOutput.FILE;
|
||||
|
||||
/**
|
||||
* The log patten. Default is "%level %timestamp %thread %class : %msg %throwable".
|
||||
* Each conversion specifiers starts with a percent sign '%' and fis followed by conversion word.
|
||||
* There are some default conversion specifiers:
|
||||
* %thread = ThreadName
|
||||
* %level = LogLevel {@link LogLevel}
|
||||
* %timestamp = The now() who format is 'yyyy-MM-dd HH:mm:ss:SSS'
|
||||
* %class = SimpleName of TargetClass
|
||||
* %msg = Message of user input
|
||||
* %throwable = Throwable of user input
|
||||
* %agent_name = ServiceName of Agent {@link Agent#SERVICE_NAME}
|
||||
* The log patten. Default is "%level %timestamp %thread %class : %msg %throwable". Each conversion specifiers
|
||||
* starts with a percent sign '%' and fis followed by conversion word. There are some default conversion
|
||||
* specifiers: %thread = ThreadName %level = LogLevel {@link LogLevel} %timestamp = The now() who format is
|
||||
* 'yyyy-MM-dd HH:mm:ss:SSS' %class = SimpleName of TargetClass %msg = Message of user input %throwable =
|
||||
* Throwable of user input %agent_name = ServiceName of Agent {@link Agent#SERVICE_NAME}
|
||||
*
|
||||
* @see org.apache.skywalking.apm.agent.core.logging.core.PatternLogger#DEFAULT_CONVERTER_MAP
|
||||
*
|
||||
*/
|
||||
public static String PATTERN = "%level %timestamp %thread %class : %msg %throwable";
|
||||
}
|
||||
|
|
@ -203,7 +194,8 @@ public class Config {
|
|||
|
||||
public static class MongoDB {
|
||||
/**
|
||||
* If true, trace all the parameters in MongoDB access, default is false. Only trace the operation, not include parameters.
|
||||
* If true, trace all the parameters in MongoDB access, default is false. Only trace the operation, not
|
||||
* include parameters.
|
||||
*/
|
||||
public static boolean TRACE_PARAM = false;
|
||||
}
|
||||
|
|
@ -230,27 +222,29 @@ public class Config {
|
|||
|
||||
public static class SpringMVC {
|
||||
/**
|
||||
* If true, the fully qualified method name will be used as the endpoint name instead of the request URL, default is false.
|
||||
* If true, the fully qualified method name will be used as the endpoint name instead of the request URL,
|
||||
* default is false.
|
||||
*/
|
||||
public static boolean USE_QUALIFIED_NAME_AS_ENDPOINT_NAME = false;
|
||||
}
|
||||
|
||||
public static class Toolkit {
|
||||
/**
|
||||
* If true, the fully qualified method name will be used as the operation name instead of the given operation name, default is false.
|
||||
* If true, the fully qualified method name will be used as the operation name instead of the given
|
||||
* operation name, default is false.
|
||||
*/
|
||||
public static boolean USE_QUALIFIED_NAME_AS_OPERATION_NAME = false;
|
||||
}
|
||||
|
||||
public static class MySQL {
|
||||
/**
|
||||
* If set to true, the parameters of the sql (typically {@link java.sql.PreparedStatement})
|
||||
* would be collected.
|
||||
* If set to true, the parameters of the sql (typically {@link java.sql.PreparedStatement}) would be
|
||||
* collected.
|
||||
*/
|
||||
public static boolean TRACE_SQL_PARAMETERS = false;
|
||||
/**
|
||||
* For the sake of performance, SkyWalking won't save the entire parameters string into the tag,
|
||||
* but only the first {@code SQL_PARAMETERS_MAX_LENGTH} characters.
|
||||
* For the sake of performance, SkyWalking won't save the entire parameters string into the tag, but only
|
||||
* the first {@code SQL_PARAMETERS_MAX_LENGTH} characters.
|
||||
*
|
||||
* Set a negative number to save the complete parameter string to the tag.
|
||||
*/
|
||||
|
|
@ -259,7 +253,8 @@ public class Config {
|
|||
|
||||
public static class SolrJ {
|
||||
/**
|
||||
* If true, trace all the query parameters(include deleteByIds and deleteByQuery) in Solr query request, default is false.
|
||||
* If true, trace all the query parameters(include deleteByIds and deleteByQuery) in Solr query request,
|
||||
* default is false.
|
||||
*/
|
||||
public static boolean TRACE_STATEMENT = false;
|
||||
|
||||
|
|
@ -269,5 +264,16 @@ public class Config {
|
|||
public static boolean TRACE_OPS_PARAMS = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation name group rules
|
||||
*/
|
||||
public static class OPGroup {
|
||||
/**
|
||||
* Rules for RestTemplate plugin
|
||||
*/
|
||||
public static class RestTemplate implements OPGroupDefinition {
|
||||
public static Map<String, String> RULE = new HashMap<String, String>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.conf;
|
||||
|
||||
/**
|
||||
* @author wusheng
|
||||
*/
|
||||
public interface OPGroupDefinition {
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.context;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.apache.skywalking.apm.agent.core.boot.BootService;
|
||||
import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor;
|
||||
import org.apache.skywalking.apm.agent.core.conf.Config;
|
||||
import org.apache.skywalking.apm.agent.core.conf.OPGroupDefinition;
|
||||
import org.apache.skywalking.apm.util.StringFormatGroup;
|
||||
|
||||
/**
|
||||
* Support operation name format by config. Every plugin could declare its own rule to avoid performance concerns.
|
||||
*
|
||||
* Right now, the rule is REGEX based, it definitely has much space to optimize, because basically, only `*` is required
|
||||
* to be supported.
|
||||
*
|
||||
* @author wusheng
|
||||
*/
|
||||
@DefaultImplementor
|
||||
public class OperationNameFormatService implements BootService {
|
||||
private static final Map<Class, StringFormatGroup> RULES = new ConcurrentHashMap<Class, StringFormatGroup>();
|
||||
|
||||
@Override public void prepare() throws Throwable {
|
||||
for (Class<?> ruleName : Config.Plugin.OPGroup.class.getClasses()) {
|
||||
if (!OPGroupDefinition.class.isAssignableFrom(ruleName)) {
|
||||
continue;
|
||||
}
|
||||
StringFormatGroup formatGroup = RULES.get(ruleName);
|
||||
if (formatGroup == null) {
|
||||
formatGroup = new StringFormatGroup();
|
||||
RULES.put(ruleName, formatGroup);
|
||||
}
|
||||
for (Field ruleNameField : ruleName.getFields()) {
|
||||
if (ruleNameField.getType().equals(Map.class)) {
|
||||
Map<String, String> rule = (Map<String, String>)ruleNameField.get(null);
|
||||
for (Map.Entry<String, String> entry : rule.entrySet()) {
|
||||
formatGroup.addRule(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void boot() throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onComplete() throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override public void shutdown() throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the operation name based on group rules
|
||||
*
|
||||
* @param definition in the Config
|
||||
* @param opName represents the operation name literal string
|
||||
* @return format string if rule matched or the given opName
|
||||
*/
|
||||
public String formatOperationName(Class<? extends OPGroupDefinition> definition, String opName) {
|
||||
StringFormatGroup formatGroup = RULES.get(definition);
|
||||
if (formatGroup == null) {
|
||||
return opName;
|
||||
} else {
|
||||
return formatGroup.format(opName).getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,3 +25,4 @@ org.apache.skywalking.apm.agent.core.remote.ServiceAndEndpointRegisterClient
|
|||
org.apache.skywalking.apm.agent.core.context.ContextManagerExtendService
|
||||
org.apache.skywalking.apm.agent.core.commands.CommandService
|
||||
org.apache.skywalking.apm.agent.core.commands.CommandExecutorService
|
||||
org.apache.skywalking.apm.agent.core.context.OperationNameFormatService
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public class ServiceManagerTest {
|
|||
public void testServiceDependencies() throws Exception {
|
||||
HashMap<Class, BootService> registryService = getFieldValue(ServiceManager.INSTANCE, "bootedServices");
|
||||
|
||||
assertThat(registryService.size(), is(9));
|
||||
assertThat(registryService.size(), is(10));
|
||||
|
||||
assertTraceSegmentServiceClient(ServiceManager.INSTANCE.findService(TraceSegmentServiceClient.class));
|
||||
assertContextManager(ServiceManager.INSTANCE.findService(ContextManager.class));
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
package org.apache.skywalking.apm.plugin.spring.resttemplate.async;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextManager;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
|
|
@ -33,7 +32,7 @@ public class FutureGetInterceptor implements InstanceMethodsAroundInterceptor {
|
|||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
Object[] cacheValues = (Object[])objInst.getSkyWalkingDynamicField();
|
||||
ContextManager.createLocalSpan("future/get:" + ((URI)cacheValues[0]).getPath());
|
||||
ContextManager.createLocalSpan("future/get:" + cacheValues[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -20,9 +20,12 @@ package org.apache.skywalking.apm.plugin.spring.resttemplate.async;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.conf.Config;
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextManager;
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
|
||||
import org.apache.skywalking.apm.agent.core.context.OperationNameFormatService;
|
||||
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
|
||||
|
|
@ -34,6 +37,7 @@ import org.apache.skywalking.apm.plugin.spring.commons.EnhanceCacheObjects;
|
|||
import org.springframework.http.HttpMethod;
|
||||
|
||||
public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
private OperationNameFormatService nameFormatService;
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
|
|
@ -42,15 +46,23 @@ public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor
|
|||
final HttpMethod httpMethod = (HttpMethod)allArguments[1];
|
||||
final ContextCarrier contextCarrier = new ContextCarrier();
|
||||
|
||||
if (nameFormatService == null) {
|
||||
nameFormatService = ServiceManager.INSTANCE.findService(OperationNameFormatService.class);
|
||||
}
|
||||
|
||||
String remotePeer = requestURL.getHost() + ":" + (requestURL.getPort() > 0 ? requestURL.getPort() : "https".equalsIgnoreCase(requestURL.getScheme()) ? 443 : 80);
|
||||
AbstractSpan span = ContextManager.createExitSpan(requestURL.getPath(), contextCarrier, remotePeer);
|
||||
|
||||
String formatURIPath = nameFormatService.formatOperationName(Config.Plugin.OPGroup.RestTemplate.class, requestURL.getPath());
|
||||
AbstractSpan span = ContextManager.createExitSpan(
|
||||
formatURIPath,
|
||||
contextCarrier, remotePeer);
|
||||
|
||||
span.setComponent(ComponentsDefine.SPRING_REST_TEMPLATE);
|
||||
Tags.URL.set(span, requestURL.getScheme() + "://" + requestURL.getHost() + ":" + requestURL.getPort() + requestURL.getPath());
|
||||
Tags.HTTP.METHOD.set(span, httpMethod.toString());
|
||||
SpanLayer.asHttp(span);
|
||||
Object[] cacheValues = new Object[3];
|
||||
cacheValues[0] = requestURL;
|
||||
cacheValues[0] = formatURIPath;
|
||||
cacheValues[1] = contextCarrier;
|
||||
objInst.setSkyWalkingDynamicField(cacheValues);
|
||||
}
|
||||
|
|
@ -61,8 +73,8 @@ public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor
|
|||
Object[] cacheValues = (Object[])objInst.getSkyWalkingDynamicField();
|
||||
cacheValues[2] = ContextManager.capture();
|
||||
if (ret != null) {
|
||||
URI uri = (URI)cacheValues[0];
|
||||
((EnhancedInstance)ret).setSkyWalkingDynamicField(new EnhanceCacheObjects(uri.getPath(), ComponentsDefine.SPRING_REST_TEMPLATE, SpanLayer.HTTP, (ContextSnapshot)cacheValues[2]));
|
||||
String uri = (String)cacheValues[0];
|
||||
((EnhancedInstance)ret).setSkyWalkingDynamicField(new EnhanceCacheObjects(uri, ComponentsDefine.SPRING_REST_TEMPLATE, SpanLayer.HTTP, (ContextSnapshot)cacheValues[2]));
|
||||
}
|
||||
ContextManager.stopSpan();
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,10 @@ package org.apache.skywalking.apm.plugin.spring.resttemplate.sync;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.conf.Config;
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
|
||||
import org.apache.skywalking.apm.agent.core.context.OperationNameFormatService;
|
||||
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
|
|
@ -32,6 +35,7 @@ import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
|
|||
import org.springframework.http.HttpMethod;
|
||||
|
||||
public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
private OperationNameFormatService nameFormatService;
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
|
|
@ -40,8 +44,13 @@ public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor
|
|||
final HttpMethod httpMethod = (HttpMethod)allArguments[1];
|
||||
final ContextCarrier contextCarrier = new ContextCarrier();
|
||||
|
||||
if (nameFormatService == null) {
|
||||
nameFormatService = ServiceManager.INSTANCE.findService(OperationNameFormatService.class);
|
||||
}
|
||||
|
||||
String remotePeer = requestURL.getHost() + ":" + (requestURL.getPort() > 0 ? requestURL.getPort() : "https".equalsIgnoreCase(requestURL.getScheme()) ? 443 : 80);
|
||||
AbstractSpan span = ContextManager.createExitSpan(requestURL.getPath(), contextCarrier, remotePeer);
|
||||
String formatURIPath = nameFormatService.formatOperationName(Config.Plugin.OPGroup.RestTemplate.class, requestURL.getPath());
|
||||
AbstractSpan span = ContextManager.createExitSpan(formatURIPath, contextCarrier, remotePeer);
|
||||
|
||||
span.setComponent(ComponentsDefine.SPRING_REST_TEMPLATE);
|
||||
Tags.URL.set(span, requestURL.getScheme() + "://" + requestURL.getHost() + ":" + requestURL.getPort() + requestURL.getPath());
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ property key | Description | Default |
|
|||
`plugin.mysql.sql_parameters_max_length`|If set to positive number, the `db.sql.parameters` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.|`512`|
|
||||
`plugin.solrj.trace_statement`|If true, trace all the query parameters(include deleteByIds and deleteByQuery) in Solr query request, default is false.|`false`|
|
||||
`plugin.solrj.trace_ops_params`|If true, trace all the operation parameters in Solr request, default is false.|`false`|
|
||||
`plugin.opgroup.*`|Support operation name customize group rules in different plugins. Read [Group rule supported plugins](op_name_group_rule.md)|Not set|
|
||||
|
||||
## Optional Plugins
|
||||
Java agent plugins are all pluggable. Optional plugins could be provided in `optional-plugins` folder under agent or 3rd party repositories.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
# Operation Name Group Rule
|
||||
Operation Name in auto instrumentation agent is unpredictable, some time, target application carries parameter in it, due to the parameter included in URI mostly.
|
||||
Those operation name are also as known endpoint name in most cases.
|
||||
Such as /api/checkTicket/tk/{userToken}.
|
||||
|
||||
We solved most of these cases, by leverage the parameter pattern path in framework, such as SpringMVC, Webflux, etc.
|
||||
But it is undetected in RPC client side, such as HTTP restful client.
|
||||
In this case, we have to ask the users to set the group rule manually.
|
||||
|
||||
All rules are supported to set through agent.config, system properties and system env, like other agent settings.
|
||||
- Config format, `plugin.opgroup.`plugin name`.rule[`rule name`]`=pattern regex expression
|
||||
|
||||
Multiple configuration items for a single plugin with different keys are supports, such as
|
||||
1. plugin.opgroup.resttemplate.rule[/rule1]=/path1
|
||||
1. plugin.opgroup.resttemplate.rule[/rule2]=/path2
|
||||
1. plugin.opgroup.resttemplate.rule[/rule2]=/path3
|
||||
|
||||
We have following plugins supporting operation name group.
|
||||
|
||||
| Plugin | Config Key | Example |
|
||||
|:----:|:-----:|:----|
|
||||
|RestTemplate| plugin.opgroup.resttemplate.rule | plugin.opgroup.resttemplate.rule[/user/auth/{token}]=`\/user\/auth\/.*` |
|
||||
|
|
@ -68,6 +68,7 @@ or providing commercial products including Apache SkyWalking.
|
|||
1. Rongjinbao. 深圳融金宝互联网金融服务有限公司. http://www.rjb777.com
|
||||
1. Shouqi Limousine & chauffeur Group 首约科技(北京)有限公司. https://www.01zhuanche.com/
|
||||
1. shuaibaoshop.com 宁波鲸灵网络科技有限公司 http://www.shuaibaoshop.com/
|
||||
1. shuyun.com 杭州数云信息技术有限公司 http://www.shuyun.com/
|
||||
1. Sijibao.com 司机宝 https://www.sijibao.com/
|
||||
1. Sinolink Securities Co.,Ltd. 国金证券佣金宝 http://www.yongjinbao.com.cn/
|
||||
1. Source++ https://sourceplusplus.com
|
||||
|
|
|
|||
Loading…
Reference in New Issue