Skip to content

OSGi classloading workaround + refactor servlet contants#2418

Merged
SylvainJuge merged 13 commits intoelastic:mainfrom
SylvainJuge:debug-osgi-classloading
Mar 17, 2022
Merged

OSGi classloading workaround + refactor servlet contants#2418
SylvainJuge merged 13 commits intoelastic:mainfrom
SylvainJuge:debug-osgi-classloading

Conversation

@SylvainJuge
Copy link
Member

@SylvainJuge SylvainJuge commented Jan 26, 2022

Add debug logging to help understanding what could cause #2104

UPDATE: re-purposing this PR

  • avoid loading our Servlet instrumentation with OSGi bundles that only import parts of the Servlet API.
  • refactor servlet instrumentation constants.
  • avoid SecurityException thrown by Apache Sling

Fixes #2104

@ghost
Copy link

ghost commented Jan 26, 2022

💚 Build Succeeded

the below badges are clickable and redirect to their specific view in the CI or DOCS
Pipeline View Test View Changes Artifacts preview preview

Expand to view the summary

Build stats

  • Start Time: 2022-03-17T08:58:58.586+0000

  • Duration: 52 min 0 sec

Test stats 🧪

Test Results
Failed 0
Passed 2745
Skipped 20
Total 2765

💚 Flaky test report

Tests succeeded.

🤖 GitHub comments

To re-run your PR in the CI, just comment with:

  • /test : Re-trigger the build.

  • run benchmark tests : Run the benchmark tests.

  • run jdk compatibility tests : Run the JDK Compatibility tests.

  • run integration tests : Run the Agent Integration tests.

  • run end-to-end tests : Run the APM-ITs.

  • run windows tests : Build & tests on windows.

  • run elasticsearch-ci/docs : Re-trigger the docs validation. (use unformatted text in the comment!)

…ingConfigurationTest.java

Co-authored-by: eyalkoren <41850454+eyalkoren@users.noreply.github.com>
@SylvainJuge SylvainJuge added the ci:agent-integration Enables agent integration tests in build pipeline label Feb 24, 2022
@SylvainJuge SylvainJuge changed the title [debug] osgi classloading debug Feb 24, 2022
Comment on lines +129 to +131
// OSGi bundles might only include 'jakarta.servlet' and not 'jakarta.servlet.http' (same for `java.servlet`), hence
// this allows to disable instrumentation as it is required for our instrumentation code.
.and(CustomElementMatchers.classLoaderCanLoadClass(osgiClassloaderFilterClass));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[for reviewer] this is what provides the work-around for OSGi by requiring ability to load a class in javax.servlet.http.* or jakarta.servlet.http.* packages.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workaround assumes that at least one class on the execution stack is loaded by a class loader that knows both javax.servlet and javax.servlet.http. So far it seems to be a valid concept, but let's keep that in mind as a possible source for future reports on missing endpoints.

@SylvainJuge
Copy link
Member Author

I have also added a simple work-around for Apache Sling throwing SecurityException, see #2104 (comment) for context.

ClassLoader servletContextClassLoader = adapter.getClassLoader(servletContext);
ClassLoader servletContextClassLoader = null;

if (!servletContext.getClass().getName().startsWith("org.apache.sling")) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[for reviewer] we explicitly exclude Apache sling implementation here (and not in the adapter) as it allows to also cover the case where it's migrated to jakarta.servlet, The downside of this is that the service name detection might not work as expected, but with Sling it creates 7+ distinct services for a simple demo app, thus we can expect users to set their service_name explicitly.

@SylvainJuge SylvainJuge marked this pull request as ready for review March 16, 2022 15:31
@SylvainJuge SylvainJuge requested a review from eyalkoren March 16, 2022 15:33
@github-actions
Copy link

/test

Copy link
Contributor

@eyalkoren eyalkoren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like the refactoring! 👏
A negative added-removed balance in PR lines is a great indication for something good 😄

The main comment is about losing class loader references within class loaders. I prefer we only do that on special cases. Class loaders refs within class loaders should represent the delegation hierarchy as much as possible in my opinion.

Comment on lines +133 to +139
@Override
public String toString() {
return "DiscriminatingMultiParentClassLoader{" +
"agentClassLoader = " + parents.get(0) + " discriminator = "+ discriminators.get(0) +
", targetClassLoader =" + parents.get(1) + " discriminator = " + discriminators.get(1) +
'}';
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

public String toString() {
return "ExternalPluginClassLoader{" +
"pluginJar=" + pluginJar +
", agentClassLoader=" + agentClassLoader +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could that be something other than the single agent CL?

Comment on lines +129 to +131
// OSGi bundles might only include 'jakarta.servlet' and not 'jakarta.servlet.http' (same for `java.servlet`), hence
// this allows to disable instrumentation as it is required for our instrumentation code.
.and(CustomElementMatchers.classLoaderCanLoadClass(osgiClassloaderFilterClass));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workaround assumes that at least one class on the execution stack is loaded by a class loader that knows both javax.servlet and javax.servlet.http. So far it seems to be a valid concept, but let's keep that in mind as a possible source for future reports on missing endpoints.

String servletResponseClassName() {
return "jakarta.servlet.ServletResponse";
public Constants.ServletImpl getImplConstants() {
return Constants.ServletImpl.JAKARTA;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's nice!

@SylvainJuge SylvainJuge enabled auto-merge (squash) March 17, 2022 09:01
@SylvainJuge SylvainJuge merged commit cb870b0 into elastic:main Mar 17, 2022
@SylvainJuge SylvainJuge deleted the debug-osgi-classloading branch March 28, 2022 07:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-java ci:agent-integration Enables agent integration tests in build pipeline

2 participants