Finish instrument codes. But with a byte buddy bug, not support instrument inner class.
This commit is contained in:
parent
fafd17f2ba
commit
67ebaf3a6f
|
|
@ -23,5 +23,10 @@
|
|||
<artifactId>gson</artifactId>
|
||||
<version>2.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<version>1.7.8</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -31,6 +31,7 @@ import java.util.ServiceLoader;
|
|||
*/
|
||||
public class ModuleManager {
|
||||
private Map<String, Module> loadedModules = new HashMap<>();
|
||||
private boolean isServiceInstrument = false;
|
||||
|
||||
/**
|
||||
* Init the given modules
|
||||
|
|
@ -83,4 +84,12 @@ public class ModuleManager {
|
|||
return module;
|
||||
throw new ModuleNotFoundException(moduleName + " missing.");
|
||||
}
|
||||
|
||||
public boolean isServiceInstrument() {
|
||||
return isServiceInstrument;
|
||||
}
|
||||
|
||||
public void setServiceInstrument(boolean serviceInstrument) {
|
||||
isServiceInstrument = serviceInstrument;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ package org.skywalking.apm.collector.core.module;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import org.skywalking.apm.collector.core.module.instrument.ServiceInstrumentation;
|
||||
|
||||
/**
|
||||
* The <code>ModuleProvider</code> is an implementation of a {@link Module}.
|
||||
|
|
@ -90,6 +91,9 @@ public abstract class ModuleProvider {
|
|||
protected final void registerServiceImplementation(Class<? extends Service> serviceType,
|
||||
Service service) throws ServiceNotProvidedException {
|
||||
if (serviceType.isInstance(service)) {
|
||||
if (manager.isServiceInstrument()) {
|
||||
service = ServiceInstrumentation.INSTANCE.buildServiceUnderMonitor(service);
|
||||
}
|
||||
this.services.put(serviceType, service);
|
||||
} else {
|
||||
throw new ServiceNotProvidedException(serviceType + " is not implemented by " + service);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright 2017, OpenSkywalking Organization All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Project repository: https://github.com/OpenSkywalking/skywalking
|
||||
*/
|
||||
|
||||
package org.skywalking.apm.collector.core.module.instrument;
|
||||
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.skywalking.apm.collector.core.module.Service;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* @author wu-sheng
|
||||
*/
|
||||
public enum ServiceInstrumentation {
|
||||
INSTANCE;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ServiceInstrumentation.class);
|
||||
private ElementMatcher<? super MethodDescription> excludeObjectMethodsMatcher;
|
||||
|
||||
public Service buildServiceUnderMonitor(Service implementation) {
|
||||
if (TracedService.class.isInstance(implementation)) {
|
||||
// Duplicate service instrument, ignore.
|
||||
return implementation;
|
||||
}
|
||||
try {
|
||||
return new ByteBuddy().subclass(implementation.getClass())
|
||||
.implement(TracedService.class)
|
||||
.method(getDefaultMatcher()).intercept(
|
||||
MethodDelegation.withDefaultConfiguration().to(new ServiceMetricCollector())
|
||||
).make().load(getClass().getClassLoader()
|
||||
).getLoaded().newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
logger.error("Create instrumented service " + implementation.getClass() + " fail.", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.error("Create instrumented service " + implementation.getClass() + " fail.", e);
|
||||
}
|
||||
return implementation;
|
||||
}
|
||||
|
||||
private ElementMatcher<? super MethodDescription> getDefaultMatcher() {
|
||||
if (excludeObjectMethodsMatcher == null) {
|
||||
excludeObjectMethodsMatcher = not(isStatic().or(named("getClass")).or(named("hashCode")).or(named("equals")).or(named("clone"))
|
||||
.or(named("toString")).or(named("notify")).or(named("notifyAll")).or(named("wait")).or(named("finalize")));
|
||||
}
|
||||
return excludeObjectMethodsMatcher;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2017, OpenSkywalking Organization All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Project repository: https://github.com/OpenSkywalking/skywalking
|
||||
*/
|
||||
|
||||
package org.skywalking.apm.collector.core.module.instrument;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
/**
|
||||
* @author wu-sheng
|
||||
*/
|
||||
public class ServiceMetricCollector {
|
||||
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object obj,
|
||||
@AllArguments Object[] allArguments,
|
||||
@SuperCall Callable<?> zuper,
|
||||
@Origin Method method
|
||||
) throws Throwable {
|
||||
return zuper.call();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2017, OpenSkywalking Organization All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Project repository: https://github.com/OpenSkywalking/skywalking
|
||||
*/
|
||||
|
||||
package org.skywalking.apm.collector.core.module.instrument;
|
||||
|
||||
import org.skywalking.apm.collector.core.module.ModuleManager;
|
||||
|
||||
/**
|
||||
* The <code>TracedService</code> implementation are dynamic class, generated by {@link ServiceInstrumentation}, when
|
||||
* {@link ModuleManager#isServiceInstrument} is true.
|
||||
*
|
||||
* By that, all the services metrics are collected, and report in the certain cycle through console.
|
||||
*
|
||||
* @author wu-sheng
|
||||
*/
|
||||
public interface TracedService {
|
||||
}
|
||||
|
|
@ -19,6 +19,17 @@
|
|||
package org.skywalking.apm.collector.core.module;
|
||||
|
||||
import java.util.Properties;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.junit.Test;
|
||||
import org.skywalking.apm.collector.core.module.instrument.ServiceMetricCollector;
|
||||
import org.skywalking.apm.collector.core.module.instrument.TracedService;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* @author wu-sheng
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@
|
|||
|
||||
package org.skywalking.apm.collector.core.module;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.skywalking.apm.collector.core.module.instrument.TracedService;
|
||||
|
||||
/**
|
||||
* @author wu-sheng
|
||||
|
|
@ -37,4 +39,21 @@ public class ModuleManagerTest {
|
|||
BaseModuleA.ServiceABusiness1 serviceABusiness1 = manager.find("BaseA").provider().getService(BaseModuleA.ServiceABusiness1.class);
|
||||
serviceABusiness1.print();
|
||||
}
|
||||
|
||||
//@Test
|
||||
public void testInstrument() throws ServiceNotProvidedException, ModuleNotFoundException, ProviderNotFoundException, DuplicateProviderException {
|
||||
ApplicationConfiguration configuration = new ApplicationConfiguration();
|
||||
configuration.addModule("Test").addProviderConfiguration("TestModule-Provider", null);
|
||||
configuration.addModule("BaseA").addProviderConfiguration("P-A",null);
|
||||
configuration.addModule("BaseB").addProviderConfiguration("P-B",null);
|
||||
|
||||
ModuleManager manager = new ModuleManager();
|
||||
manager.setServiceInstrument(true);
|
||||
manager.init(configuration);
|
||||
|
||||
BaseModuleA.ServiceABusiness1 serviceABusiness1 = manager.find("BaseA").provider().getService(BaseModuleA.ServiceABusiness1.class);
|
||||
serviceABusiness1.print();
|
||||
|
||||
Assert.assertTrue(serviceABusiness1 instanceof TracedService);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue