Add `plugin.jdbc.trace_sql_parameters` into Configuration Discovery S… (#174)
Co-authored-by: yuzhongyu <yuzhongyu@cestc.cn>
This commit is contained in:
parent
a8214514ae
commit
e81638ea4e
|
|
@ -19,6 +19,7 @@ Release Notes.
|
|||
* Fix Span not finished in gateway plugin when the gateway request timeout.
|
||||
* Support `-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector` in gRPC log report.
|
||||
* Fix tcnative libraries relocation for aarch64.
|
||||
* Add `plugin.jdbc.trace_sql_parameters` into Configuration Discovery Service.
|
||||
|
||||
#### Documentation
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
|
|||
import org.apache.skywalking.apm.agent.core.remote.GRPCChannelListener;
|
||||
import org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager;
|
||||
import org.apache.skywalking.apm.agent.core.remote.GRPCChannelStatus;
|
||||
import org.apache.skywalking.apm.agent.core.util.CollectionUtil;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.ConfigurationDiscoveryServiceGrpc;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.ConfigurationSyncRequest;
|
||||
import org.apache.skywalking.apm.network.common.v3.Commands;
|
||||
|
|
@ -118,10 +119,16 @@ public class ConfigurationDiscoveryService implements BootService, GRPCChannelLi
|
|||
*
|
||||
* @param watcher dynamic configuration watcher
|
||||
*/
|
||||
public void registerAgentConfigChangeWatcher(AgentConfigChangeWatcher watcher) {
|
||||
public synchronized void registerAgentConfigChangeWatcher(AgentConfigChangeWatcher watcher) {
|
||||
WatcherHolder holder = new WatcherHolder(watcher);
|
||||
if (register.containsKey(holder.getKey())) {
|
||||
throw new IllegalStateException("Duplicate register, watcher=" + watcher);
|
||||
List<WatcherHolder> watcherHolderList = register.get(holder.getKey());
|
||||
for (WatcherHolder watcherHolder : watcherHolderList) {
|
||||
if (watcherHolder.getWatcher().getClass().equals(watcher.getClass())) {
|
||||
LOGGER.debug("Duplicate register, watcher={}", watcher);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
register.put(holder.getKey(), holder);
|
||||
}
|
||||
|
|
@ -142,31 +149,33 @@ public class ConfigurationDiscoveryService implements BootService, GRPCChannelLi
|
|||
|
||||
config.forEach(property -> {
|
||||
String propertyKey = property.getKey();
|
||||
WatcherHolder holder = register.get(propertyKey);
|
||||
if (holder != null) {
|
||||
AgentConfigChangeWatcher watcher = holder.getWatcher();
|
||||
String newPropertyValue = property.getValue();
|
||||
if (StringUtil.isBlank(newPropertyValue)) {
|
||||
if (watcher.value() != null) {
|
||||
// Notify watcher, the new value is null with delete event type.
|
||||
watcher.notify(
|
||||
new AgentConfigChangeWatcher.ConfigChangeEvent(
|
||||
null, AgentConfigChangeWatcher.EventType.DELETE
|
||||
));
|
||||
List<WatcherHolder> holderList = register.get(propertyKey);
|
||||
for (WatcherHolder holder : holderList) {
|
||||
if (holder != null) {
|
||||
AgentConfigChangeWatcher watcher = holder.getWatcher();
|
||||
String newPropertyValue = property.getValue();
|
||||
if (StringUtil.isBlank(newPropertyValue)) {
|
||||
if (watcher.value() != null) {
|
||||
// Notify watcher, the new value is null with delete event type.
|
||||
watcher.notify(
|
||||
new AgentConfigChangeWatcher.ConfigChangeEvent(
|
||||
null, AgentConfigChangeWatcher.EventType.DELETE
|
||||
));
|
||||
} else {
|
||||
// Don't need to notify, stay in null.
|
||||
}
|
||||
} else {
|
||||
// Don't need to notify, stay in null.
|
||||
if (!newPropertyValue.equals(watcher.value())) {
|
||||
watcher.notify(new AgentConfigChangeWatcher.ConfigChangeEvent(
|
||||
newPropertyValue, AgentConfigChangeWatcher.EventType.MODIFY
|
||||
));
|
||||
} else {
|
||||
// Don't need to notify, stay in the same config value.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!newPropertyValue.equals(watcher.value())) {
|
||||
watcher.notify(new AgentConfigChangeWatcher.ConfigChangeEvent(
|
||||
newPropertyValue, AgentConfigChangeWatcher.EventType.MODIFY
|
||||
));
|
||||
} else {
|
||||
// Don't need to notify, stay in the same config value.
|
||||
}
|
||||
LOGGER.warn("Config {} from OAP, doesn't match any watcher, ignore.", propertyKey);
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("Config {} from OAP, doesn't match any watcher, ignore.", propertyKey);
|
||||
}
|
||||
});
|
||||
this.uuid = responseUuid;
|
||||
|
|
@ -238,17 +247,25 @@ public class ConfigurationDiscoveryService implements BootService, GRPCChannelLi
|
|||
* Local dynamic configuration center.
|
||||
*/
|
||||
public static class Register {
|
||||
private final Map<String, WatcherHolder> register = new HashMap<>();
|
||||
private final Map<String, List<WatcherHolder>> register = new HashMap<>();
|
||||
|
||||
private boolean containsKey(String key) {
|
||||
return register.containsKey(key);
|
||||
}
|
||||
|
||||
private void put(String key, WatcherHolder holder) {
|
||||
register.put(key, holder);
|
||||
List<WatcherHolder> watcherHolderList = register.get(key);
|
||||
if (CollectionUtil.isEmpty(watcherHolderList)) {
|
||||
ArrayList<WatcherHolder> newWatchHolderList = new ArrayList<>();
|
||||
newWatchHolderList.add(holder);
|
||||
register.put(key, newWatchHolderList);
|
||||
} else {
|
||||
watcherHolderList.add(holder);
|
||||
register.put(key, watcherHolderList);
|
||||
}
|
||||
}
|
||||
|
||||
public WatcherHolder get(String name) {
|
||||
public List<WatcherHolder> get(String name) {
|
||||
return register.get(name);
|
||||
}
|
||||
|
||||
|
|
@ -259,12 +276,13 @@ public class ConfigurationDiscoveryService implements BootService, GRPCChannelLi
|
|||
@Override
|
||||
public String toString() {
|
||||
ArrayList<String> registerTableDescription = new ArrayList<>(register.size());
|
||||
register.forEach((key, holder) -> {
|
||||
AgentConfigChangeWatcher watcher = holder.getWatcher();
|
||||
registerTableDescription.add(new StringBuilder().append("key:")
|
||||
.append(key)
|
||||
.append("value(current):")
|
||||
.append(watcher.value()).toString());
|
||||
register.forEach((key, holderList) -> {
|
||||
for (WatcherHolder holder : holderList) {
|
||||
registerTableDescription.add(new StringBuilder().append("key:")
|
||||
.append(key)
|
||||
.append("value(current):")
|
||||
.append(holder.getWatcher().value()).toString());
|
||||
}
|
||||
});
|
||||
return registerTableDescription.stream().collect(Collectors.joining(",", "[", "]"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ package org.apache.skywalking.apm.plugin.jdbc;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.conf.dynamic.ConfigurationDiscoveryService;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.plugin.jdbc.connectionurl.parser.URLParser;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
|
|
@ -34,7 +37,10 @@ public class JDBCDriverInterceptor implements InstanceMethodsAroundInterceptor {
|
|||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
|
||||
TraceSqlParametersWatcher traceSqlParametersWatcher = new TraceSqlParametersWatcher("plugin.jdbc.trace_sql_parameters");
|
||||
ConfigurationDiscoveryService configurationDiscoveryService = ServiceManager.INSTANCE.findService(
|
||||
ConfigurationDiscoveryService.class);
|
||||
configurationDiscoveryService.registerAgentConfigChangeWatcher(traceSqlParametersWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public class JDBCPluginConfig {
|
|||
* If set to true, the parameters of the sql (typically {@link java.sql.PreparedStatement}) would be
|
||||
* collected.
|
||||
*/
|
||||
public static boolean TRACE_SQL_PARAMETERS = false;
|
||||
public static volatile 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.
|
||||
|
|
|
|||
|
|
@ -40,11 +40,10 @@ public class PSSetterDefinitionOfJDBCInstrumentation implements InstanceMethodsI
|
|||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
ElementMatcher.Junction<MethodDescription> matcher = none();
|
||||
|
||||
if (JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS) {
|
||||
final Set<String> setters = ignorable ? PS_IGNORABLE_SETTERS : PS_SETTERS;
|
||||
for (String setter : setters) {
|
||||
matcher = matcher.or(named(setter));
|
||||
}
|
||||
// remove TRACE_SQL_PARAMETERS judgement for dynamic config
|
||||
final Set<String> setters = ignorable ? PS_IGNORABLE_SETTERS : PS_SETTERS;
|
||||
for (String setter : setters) {
|
||||
matcher = matcher.or(named(setter));
|
||||
}
|
||||
|
||||
return matcher;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.plugin.jdbc;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.conf.dynamic.AgentConfigChangeWatcher;
|
||||
|
||||
public class TraceSqlParametersWatcher extends AgentConfigChangeWatcher {
|
||||
|
||||
private final boolean defaultValue;
|
||||
|
||||
public TraceSqlParametersWatcher(String propertyKey) {
|
||||
super(propertyKey);
|
||||
defaultValue = JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notify(ConfigChangeEvent value) {
|
||||
if (EventType.DELETE.equals(value.getEventType())) {
|
||||
JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS = defaultValue;
|
||||
} else {
|
||||
JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS = Boolean.parseBoolean(value.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String value() {
|
||||
return Boolean.toString(JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.plugin.jdbc.mysql.v5.define;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
import org.apache.skywalking.apm.plugin.jdbc.define.AbstractDriverInstrumentation;
|
||||
|
||||
import static org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch.byMultiClassMatch;
|
||||
|
||||
/**
|
||||
* {@link DriverInstrumentation} presents that skywalking intercepts {@link com.mysql.jdbc.Driver}.
|
||||
*/
|
||||
public class DriverInstrumentation extends AbstractDriverInstrumentation {
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return byMultiClassMatch("com.mysql.jdbc.Driver", "com.mysql.cj.jdbc.Driver", "com.mysql.jdbc.NonRegisteringDriver");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] witnessClasses() {
|
||||
return new String[] {Constants.WITNESS_MYSQL_5X_CLASS};
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
mysql-5.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v5.define.DriverInstrumentation
|
||||
mysql-5.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v5.define.Mysql5xConnectionInstrumentation
|
||||
mysql-5.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v5.define.Mysql50ConnectionInstrumentation
|
||||
mysql-5.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v5.define.CallableInstrumentation
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
import org.apache.skywalking.apm.plugin.jdbc.define.AbstractDriverInstrumentation;
|
||||
|
||||
import static org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch.byMultiClassMatch;
|
||||
|
||||
/**
|
||||
* {@link DriverInstrumentation} presents that skywalking intercepts {@link com.mysql.jdbc.Driver}.
|
||||
*/
|
||||
public class DriverInstrumentation extends AbstractDriverInstrumentation {
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return byMultiClassMatch("com.mysql.jdbc.Driver", "com.mysql.cj.jdbc.Driver", "com.mysql.jdbc.NonRegisteringDriver");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] witnessClasses() {
|
||||
return new String[] {Constants.WITNESS_MYSQL_8X_CLASS};
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.DriverInstrumentation
|
||||
mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.ConnectionImplCreateInstrumentation
|
||||
mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.ConnectionInstrumentation
|
||||
mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.CallableInstrumentation
|
||||
|
|
@ -22,4 +23,4 @@ mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.StatementInstrum
|
|||
mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.PreparedStatementSetterInstrumentation
|
||||
mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.PreparedStatementNullSetterInstrumentation
|
||||
mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.PreparedStatementIgnoredSetterInstrumentation
|
||||
mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.CacheIpsInstrumentation
|
||||
mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.CacheIpsInstrumentation
|
||||
|
|
|
|||
|
|
@ -16,23 +16,22 @@ Every plugin maintained in the main repo requires corresponding test cases as we
|
|||
|
||||
## Case Base Image Introduction
|
||||
|
||||
The test framework provides `JVM-container` and `Tomcat-container` base images including JDK8 and JDK14. You can choose the best one for your test case. If both are suitable for your case, **`JVM-container` is preferred**.
|
||||
The test framework provides `JVM-container` and `Tomcat-container` base images including JDK8 and JDK17. You can choose the best one for your test case. If both are suitable for your case, **`JVM-container` is preferred**.
|
||||
|
||||
### JVM-container Image Introduction
|
||||
|
||||
[JVM-container](../../../../../test/plugin/containers/jvm-container) uses `adoptopenjdk/openjdk8:alpine-jre` as the base image. `JVM-container` supports JDK14 and JDK17 as well in CI, which inherits `adoptopenjdk/openjdk8:alpine-jre` and `eclipse-temurin:17-alpine`.
|
||||
[JVM-container](../../../../../test/plugin/containers/jvm-container) uses `adoptopenjdk/openjdk8:alpine-jre` as the base image. `JVM-container` supports JDK8 and JDK17 as well in CI, which inherits `adoptopenjdk/openjdk8:alpine-jre` and `eclipse-temurin:17-alpine`.
|
||||
It is supported to custom the base Java docker image by specify `base_image_java`.
|
||||
The test case project must be packaged as `project-name.zip`, including `startup.sh` and uber jar, by using `mvn clean package`.
|
||||
|
||||
Take the following test projects as examples:
|
||||
* [sofarpc-scenario](../../../../../test/plugin/scenarios/sofarpc-scenario) is a single project case.
|
||||
* [webflux-scenario](../../../../../test/plugin/scenarios/webflux-scenario) is a case including multiple projects.
|
||||
* [jdk14-with-gson-scenario](../../../../../test/plugin/scenarios/jdk14-with-gson-scenario) is a single project case with JDK14.
|
||||
* [jdk17-with-gson-scenario](../../../../../test/plugin/scenarios/jdk17-with-gson-scenario) is a single project case with JDK17.
|
||||
|
||||
### Tomcat-container Image Introduction
|
||||
|
||||
[Tomcat-container](../../../../../test/plugin/containers/tomcat-container) uses `tomcat:8.5-jdk8-openjdk`, `tomcat:8.5-jdk14-openjdk`, `tomcat:8.5-jdk17-openjdk` as the base image.
|
||||
[Tomcat-container](../../../../../test/plugin/containers/tomcat-container) uses `tomcat:8.5-jdk8-openjdk`, `tomcat:8.5-jdk17-openjdk` as the base image.
|
||||
It is supported to custom the base Tomcat docker image by specify `base_image_tomcat`.
|
||||
The test case project must be packaged as `project-name.war` by using `mvn package`.
|
||||
|
||||
|
|
@ -623,7 +622,7 @@ Every test case is a GitHub Actions Job. Please use the scenario directory name
|
|||
mostly you'll just need to decide which file (`plugins-test.<n>.yaml`) to add your test case, and simply put one line (as follows) in it, take the existed cases as examples.
|
||||
You can run `python3 tools/select-group.py` to see which file contains the least cases and add your cases into it, in order to balance the running time of each group.
|
||||
|
||||
If a test case required to run in JDK 14 environment, please add you test case into file `plugins-jdk14-test.<n>.yaml`.
|
||||
If a test case required to run in JDK 17 environment, please add you test case into file `plugins-jdk17-test.<n>.yaml`.
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
|
|
|
|||
|
|
@ -28,5 +28,6 @@ Java agent supports the following dynamic configurations.
|
|||
| agent.ignore_suffix | If the operation name of the first span is included in this set, this segment should be ignored. Multiple values should be separated by `,` | `.txt,.log` | - |
|
||||
| agent.trace.ignore_path | The value is the path that you need to ignore, multiple paths should be separated by `,` [more details](./agent-optional-plugins/trace-ignore-plugin.md) | `/your/path/1/**,/your/path/2/**` | `apm-trace-ignore-plugin` |
|
||||
| agent.span_limit_per_segment | The max number of spans per segment. | `300` | - |
|
||||
| plugin.jdbc.trace_sql_parameters | If set to true, the parameters of the sql (typically java.sql.PreparedStatement) would be collected. | `false` | - |
|
||||
|
||||
* `Required plugin(s)`, the configuration affects only when the required plugins activated.
|
||||
|
|
|
|||
Loading…
Reference in New Issue