elastic / apm-agent-java

https://www.elastic.co/guide/en/apm/agent/java/current/index.html
Apache License 2.0
567 stars 321 forks source link

Support Spring non-web services #1225

Open jerfer opened 4 years ago

jerfer commented 4 years ago

Is your feature request related to a problem?

I have some simple Spring Boot 2.1.x through 2.3.x applications that get messages from queues and process these using back-end services shared with other systems. These simple applications do not need a web server and are configured with: spring.main.web-application-type=none

Attaching the Elastic APM Java Agent to these causes a: java.lang.IllegalStateException: Cannot resolve type description for javax.servlet.ServletContext

Describe the solution you'd like

I would like to be able to monitor these systems as I currently do for Spring Boot Servlet applications. They would likely initiate their own Traces since they're processing messages asynchronously.

Describe alternatives you've considered

I could configure these as Servlet applications but that would defeat the purpose of keeping them small and light and would require more runtime resources, increasing the cost of operating them.

felixbarny commented 4 years ago

Besides that exception, the real issue is that we might not support the message frameworks you are using. Which queues are you using and which libraries for interacting with them?

Could you also share the full stack trace of that exception?

jerfer commented 4 years ago

Currently, AWS SQS and SNS via Spring Cloud Messaging for AWS is what's used. This may change, as we're currently exploring other messaging systems. Am I correct in assuming that for the time being, the only way to integrate these types of systems is via direct use of the public APIs (Tracer, Transaction, Span)?

Here's the stack trace:

java.lang.IllegalStateException: Cannot resolve type description for javax.servlet.ServletContext
  at co.elastic.apm.agent.shaded.bytebuddy.pool.TypePool$Resolution$Illegal.resolve(TypePool.java:159)
  at co.elastic.apm.agent.shaded.bytebuddy.pool.TypePool$Default$LazyTypeDescription$TokenizedGenericType.toErasure(TypePool.java:6241)
  at co.elastic.apm.agent.shaded.bytebuddy.pool.TypePool$Default$LazyTypeDescription$GenericTypeToken$Resolution$Raw$RawAnnotatedType.of(TypePool.java:3412)
  at co.elastic.apm.agent.shaded.bytebuddy.pool.TypePool$Default$LazyTypeDescription$GenericTypeToken$Resolution$Raw.resolveReturnType(TypePool.java:3302)
  at co.elastic.apm.agent.shaded.bytebuddy.pool.TypePool$Default$LazyTypeDescription$LazyMethodDescription.getReturnType(TypePool.java:6796)
  at co.elastic.apm.agent.shaded.bytebuddy.description.method.MethodDescription$AbstractBase.asSignatureToken(MethodDescription.java:838)
  at co.elastic.apm.agent.bci.bytebuddy.FailSafeDeclaredMethodsCompiler.compile(FailSafeDeclaredMethodsCompiler.java:85)
  at co.elastic.apm.agent.bci.bytebuddy.FailSafeDeclaredMethodsCompiler.compile(FailSafeDeclaredMethodsCompiler.java:66)
  at co.elastic.apm.agent.shaded.bytebuddy.dynamic.scaffold.MethodRegistry$Default.prepare(MethodRegistry.java:471)
  at co.elastic.apm.agent.shaded.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder.make(RedefinitionDynamicTypeBuilder.java:198)
  at co.elastic.apm.agent.shaded.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doTransform(AgentBuilder.java:10327)
  at co.elastic.apm.agent.shaded.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10263)
  at co.elastic.apm.agent.shaded.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.access$1600(AgentBuilder.java:10029)
  at co.elastic.apm.agent.shaded.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:10722)
  at co.elastic.apm.agent.shaded.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:10660)
  at java.base/java.security.AccessController.doPrivileged(Unknown Source)
  at co.elastic.apm.agent.shaded.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10219)
  at co.elastic.apm.agent.shaded.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$ByteBuddy$ModuleSupport.transform(Unknown Source)
  at java.instrument/sun.instrument.TransformerManager.transform(Unknown Source)
  at java.instrument/sun.instrument.InstrumentationImpl.transform(Unknown Source)
  at java.base/java.lang.ClassLoader.defineClassImpl(Native Method)
  at java.base/java.lang.ClassLoader.defineClassInternal(Unknown Source)
  at java.base/java.lang.ClassLoader.defineClass(Unknown Source)
  at java.base/java.security.SecureClassLoader.defineClass(Unknown Source)
  at java.base/java.net.URLClassLoader.defineClass(Unknown Source)
  at java.base/java.net.URLClassLoader$ClassFinder.run(Unknown Source)
  at java.base/java.net.URLClassLoader$ClassFinder.run(Unknown Source)
  at java.base/java.security.AccessController.doPrivileged(Unknown Source)
  at java.base/java.net.URLClassLoader.findClass(Unknown Source)
  at java.base/java.lang.ClassLoader.loadClassHelper(Unknown Source)
  at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
  at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:93)
  at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
  at org.springframework.boot.autoconfigure.condition.FilteringSpringBootCondition$ClassNameFilter.forName(FilteringSpringBootCondition.java:135)
  at org.springframework.boot.autoconfigure.condition.FilteringSpringBootCondition$ClassNameFilter.isPresent(FilteringSpringBootCondition.java:125)
  at org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition.getOutcome(OnWebApplicationCondition.java:80)
  at org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition.getOutcomes(OnWebApplicationCondition.java:58)
  at org.springframework.boot.autoconfigure.condition.FilteringSpringBootCondition.match(FilteringSpringBootCondition.java:49)
  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.filter(AutoConfigurationImportSelector.java:246)
  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getAutoConfigurationEntry(AutoConfigurationImportSelector.java:121)
  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.process(AutoConfigurationImportSelector.java:396)
  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:875)
  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:801)
  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:771)
  at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:185)
  at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:315)
  at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232)
  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275)
  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95)
  at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705)
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531)
  at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744)
  at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391)
  at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1204)
  at com.scigilian.analyze.AwsSnsPublisherApp.main(AwsSnsPublisherApp.java:12)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at java.base/java.lang.reflect.Method.invoke(Unknown Source)
  at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
  at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
  at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
  at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52)
felixbarny commented 4 years ago

We have AWS queues on our radar but for now, the manual tracing API is the only way, yes.

jerfer commented 4 years ago

@felixbarny Thank you for confirming, Felix.

SylvainJuge commented 3 years ago

Hi @jerfer we plan to add auto-instrumentation for those services soon:

Please make sure to subscribe to those issues to get proper notifications when those are ready.