Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to Work with tomcat #260

Closed
liuxianbing opened this issue Jan 21, 2017 · 3 comments
Closed

How to Work with tomcat #260

liuxianbing opened this issue Jan 21, 2017 · 3 comments
Assignees
Labels
Milestone

Comments

@liuxianbing
Copy link

liuxianbing commented Jan 21, 2017

my tomcat version 8.0.26 bytebuddy 1.6.1
after i startup the tomcat application, use agentmain method with jvm attach

@Advice.OnMethodEnter
public static long enter() {
return System.currentTimeMillis();
}

after start the agent, aslo the AgentBuilder.RawMatcher has match my application class,but it does not inject the code to my web application

why?

@raphw
Copy link
Owner

raphw commented Jan 21, 2017

By doing the above you do not add any code with an effect. Attempt to debug your code by trying something like adding a System.out::println and see if it works.

You should also add a AgentBuilder.Listener.StreamWriting::toSystemOutput to see if your types get enhanced the way you want it.

From the little code you provide, I cannot say anything further from what is wrong.

@raphw raphw closed this as completed Jan 21, 2017
@raphw raphw self-assigned this Jan 21, 2017
@raphw raphw added the question label Jan 21, 2017
@raphw raphw added this to the 1.6.5 milestone Jan 21, 2017
@liuxianbing
Copy link
Author

liuxianbing commented Jan 21, 2017

sorry , here is the code

 final ByteBuddy byteBuddy =
        new ByteBuddy().with(TypeValidation.of(ApmConfiguration.getInstance().debug));
    // .with(MethodGraph.Empty.INSTANCE);
    return new AgentBuilder.Default(byteBuddy).with(binaryLocator)
        .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION).with(new AgentBuilder.Listener() {
          @Override
          public void onComplete(String arg0, ClassLoader arg1, JavaModule arg2) {
            // System.out.println("onComplete:" + arg0);
          }

          @Override
          public void onError(String arg0, ClassLoader arg1, JavaModule arg2, Throwable arg3) {
            System.out.println(arg3.getMessage() + "onError:" + arg0);
            arg3.printStackTrace();
          }

          @Override
          public void onIgnored(TypeDescription arg0, ClassLoader arg1, JavaModule arg2) {}

          @Override
          public void onTransformation(TypeDescription arg0, ClassLoader arg1, JavaModule arg2,
              DynamicType arg3) {
            System.out.println("onTransformation:" + arg0.getName());
          }
        }).ignore(any(), timed("classloader", "bootstrap", isBootstrapClassLoader()))
        .or(any(), timed("classloader", "reflection", isReflectionClassLoader()))
        .or(any(),
            timed("classloader", "apm-call-site",
                classLoaderWithName("org.codehaus.groovy.runtime.callsite.CallSiteClassLoader")))
        .or(any(), new IsIgnoredClassLoaderElementMatcher())
        .or(timed("type", "global-exclude",
            nameStartsWith("java").or(nameStartsWith("com.sun.")).or(nameStartsWith("sun."))
                .or(nameStartsWith("jdk.")).or(nameStartsWith("org.aspectj."))
                .or(nameStartsWith("org.groovy.")).or(nameStartsWith("com.p6spy."))
                .or(nameStartsWith("net.bytebuddy."))
                .or(nameStartsWith("org.slf4j.").and(not(nameStartsWith("org.slf4j.impl."))))
                .or(nameContains("javassist")).or(nameContains(".asm."))
                .or(nameStartsWith("com.github.apm")
                    .and(not(nameContains("Test").or(nameContains("benchmark")))))))
        .disableClassFormatChanges().type(ElementMatchers.nameStartsWith("com.jingoal.dc.koala.web.controller"))
        .transform(new AgentBuilder.Transformer() {
          @Override
          public Builder<?> transform(Builder<?> builder, TypeDescription typeDescription,
              ClassLoader arg2) {
            try {
              return builder.visit(Advice.to(LoggingAdvice.class).on(nameStartsWith("do")));
            } catch (Exception e) {
              e.printStackTrace();
            }
            return null;
          }
        }).asDecorator();

And LoggingAdvice is

@Advice.OnMethodEnter
  public static long enter() {
    return System.currentTimeMillis();
  }

  @Advice.OnMethodExit(onThrowable = Throwable.class)
  public static void exit(@Advice.Thrown Throwable t, @Advice.Origin("#m") String methodName,
      @Advice.Origin("#t") String classType, @Advice.Origin("#s") String signature,
      @Advice.Enter long startTime,
      @Advice.Return(typing = Assigner.Typing.DYNAMIC) Object returnObj) {
    long spendTime = System.currentTimeMillis() - startTime;
    System.out.println(classType + "-" + methodName + "***");
    PrometheusMetricsModule.calLate(spendTime, classType, methodName, signature);
    if (null != t) {
      PrometheusMetricsModule.errorCounter(classType, methodName, signature, t);
    }
    if (slowTime > 0 && spendTime >= slowTime) {
      writeSlowTime(classType, methodName, signature, returnObj.toString(), spendTime);
    }
  }

my web application is using spring mvc,which is deployed into the tomcat server
after i startup the tomcat, i get the jvm pid, and then attach my agent app to the running jvm

bellow is my web application

package com.jingoal.dc.koala.web.controller;
@Controller
@SessionAttributes("login")
@RequestMapping(value = "/login")
public class LoginController{
@RequestMapping("/doLogin")
  public String doLogin(@RequestParam(required = false) String inputId,
      @RequestParam(required = false) String inputPassword, Model model) {
....
}
}

and after i attach the agent to the running application,my agent listener aslo print

onTransformation:com.jingoal.dc.koala.web.controller.LoginController

is there someing different with the situation when came with spring web application?

Hope get some help, thanks!!!
forgive my poor English

@raphw
Copy link
Owner

raphw commented Jan 23, 2017

There is a chance that your application class loaders cannot see the your advice types such as PrometheusMetricsModule. Application containers such as Tomcat often shield their deployed applications from the system class path on which the agent is loaded.

What I would recommend you is to start out with a very simple advice that does not rely on any foreign types but only, for example, prints to the console. If this works, it is a class loader issue.

A common strategy is to add such required infrastructure types to the bootstrap class loader in a specific jar via the Instrumentation interface. This makes those types universally visible to all class loaders.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants