APM Java agent startup error with Adobe Experience Manager

Hi,

I'm trying to get the java APM agent running with Adobe Experience Manager (AEM), which is based on Apache Sling and runs in Apache Felix with Jetty.

I am successfully able to run a Sling standalone jar with Sling versions 8 through 10 using the latest 0.8 snapshot of the java apm agent (which also runs in Felix with Jetty), but I get errors when using the AEM jar.

AEM doesn't use an exact Sling version, it pulls in bundles from different versions of sling, but sling versions 8-10 I believe cover AEM 6.3 and 6.4 which are most used.

After starting AEM with the java APM agent and trying to access a page in AEM, I see this in the error log for any page I access:

org.eclipse.jetty.servlet.ServletHandler Error for /libs/granite/core/content/login.html java.lang.NoClassDefFoundError: co/elastic/apm/servlet/ServletApiAdvice at org.apache.felix.http.base.internal.dispatch.DispatcherServlet.service(DispatcherServlet.java:49) at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:587) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.eclipse.jetty.server.Server.handle(Server.java:499) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257) at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) at java.lang.Thread.run(Thread.java:748)

AEM is a licensed product from Adobe, so I can't provide it for troubleshooting, but I'm happy to help anyway I can. Any ideas how I can get this working with AEM?

ping @felixbarny

Thanks!

Jeremy

1 Like

Hi Jeremy and thanks for giving the Java agent a try.

This exception is a sign that the OSGi boot delegation is not working correctly.

The boot delegation is required so that all modules have access to the agent classes. The APM Java agent automatically adds the system property org.osgi.framework.bootdelegation with the value co.elastic.apm.*. See also https://github.com/elastic/apm-agent-java/blob/master/apm-agent-core/src/main/java/co/elastic/apm/bci/OsgiBootDelegationEnabler.java

However, this seems to be not enough for some OSGi containers. Some don't respect the system property but require the org.osgi.framework.bootdelegation property to be set in a specific configuration file. Does such a file come with AEM?

Cheers,
Felix

1 Like

Thanks for the hint, I updated the sling.properties file to include this, and now the APM agent is working:

sling.bootdelegation.co.elastic.apm=co.elastic.apm.*

One more question (I can open a new thread), are there any plans to have spans automatically generated when a Servlet RequestDispatcher does a forward or include?

Thanks!

We have plans to do that but are not yet sure what the best approach for that would be. We discussed several options internally

  • Creating only one Transaction which is started when the request comes in and stops after the last forward has ended (when the response is being comited).
  • Creating separate Transactions for each forward

How would you like this to work and can you give a concrete example of a request which forwards to another URL and which Transactions and spans you would like to see?

Felix,

At least for my use case with Apache Sling, it would make the most sense to use one transaction, and have each span be a forward within the transaction.

Sling's request processing engine will look for included components in an overall page being rendered, and will use forwards to render all those components. By grouping this way, it allows us to view all the individual component response times that make up the overall page render.

https://sling.apache.org/documentation/the-sling-engine/dispatching-requests.html

I'll also mention from a dashboard perspective, it would be awesome to see a chart that shows the average response time of a page that includes all of the individual spans that make up the page, instead of just being able to view the spans for individual transaction traces.

Another APM product I use automatically tracks forwards and displays the average in a graph, it is very helpful in finding component bottlenecks across a given type of page.

Thanks again for your help!

Jeremy

Felix,

This is still a work in progress, but here's some source of how I'm setting transaction names and creating spans for Sling if there is anything you want to take.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.