Search in sources :

Example 36 with Transaction

use of com.newrelic.agent.bridge.Transaction in project newrelic-java-agent by newrelic.

the class SpringController_Instrumentation method requestMapping.

@WeaveWithAnnotation(annotationClasses = { "org.springframework.web.bind.annotation.RequestMapping", "org.springframework.web.bind.annotation.PatchMapping", "org.springframework.web.bind.annotation.PutMapping", "org.springframework.web.bind.annotation.GetMapping", "org.springframework.web.bind.annotation.PostMapping", "org.springframework.web.bind.annotation.DeleteMapping" })
@WeaveIntoAllMethods
@Trace
private static void requestMapping() {
    Transaction transaction = AgentBridge.getAgent().getTransaction(false);
    if (transaction != null) {
        RequestMapping rootPathMapping = Weaver.getClassAnnotation(RequestMapping.class);
        String rootPath = null;
        if (rootPathMapping != null) {
            rootPath = SpringControllerUtility.getPathValue(rootPathMapping.value(), rootPathMapping.path());
        }
        // PUT, DELETE, POST, GET
        if (Weaver.getMethodAnnotation(RequestMapping.class) != null) {
            RequestMapping methodPathMapping = Weaver.getMethodAnnotation(RequestMapping.class);
            String methodPath = SpringControllerUtility.getPathValue(methodPathMapping.value(), methodPathMapping.path());
            processAnnotations(transaction, methodPathMapping.method(), rootPath, methodPath, MethodHandles.lookup().lookupClass());
        } else if (Weaver.getMethodAnnotation(PutMapping.class) != null) {
            PutMapping methodPathMapping = Weaver.getMethodAnnotation(PutMapping.class);
            String methodPath = SpringControllerUtility.getPathValue(methodPathMapping.value(), methodPathMapping.path());
            processAnnotations(transaction, new RequestMethod[] { RequestMethod.PUT }, rootPath, methodPath, MethodHandles.lookup().lookupClass());
        } else if (Weaver.getMethodAnnotation(DeleteMapping.class) != null) {
            DeleteMapping methodPathMapping = Weaver.getMethodAnnotation(DeleteMapping.class);
            String methodPath = SpringControllerUtility.getPathValue(methodPathMapping.value(), methodPathMapping.path());
            processAnnotations(transaction, new RequestMethod[] { RequestMethod.DELETE }, rootPath, methodPath, MethodHandles.lookup().lookupClass());
        } else if (Weaver.getMethodAnnotation(PostMapping.class) != null) {
            PostMapping methodPathMapping = Weaver.getMethodAnnotation(PostMapping.class);
            String methodPath = SpringControllerUtility.getPathValue(methodPathMapping.value(), methodPathMapping.path());
            processAnnotations(transaction, new RequestMethod[] { RequestMethod.POST }, rootPath, methodPath, MethodHandles.lookup().lookupClass());
        } else if (Weaver.getMethodAnnotation(PatchMapping.class) != null) {
            PatchMapping methodPathMapping = Weaver.getMethodAnnotation(PatchMapping.class);
            String methodPath = SpringControllerUtility.getPathValue(methodPathMapping.value(), methodPathMapping.path());
            processAnnotations(transaction, new RequestMethod[] { RequestMethod.PATCH }, rootPath, methodPath, MethodHandles.lookup().lookupClass());
        } else if (Weaver.getMethodAnnotation(GetMapping.class) != null) {
            GetMapping methodPathMapping = Weaver.getMethodAnnotation(GetMapping.class);
            String methodPath = SpringControllerUtility.getPathValue(methodPathMapping.value(), methodPathMapping.path());
            processAnnotations(transaction, new RequestMethod[] { RequestMethod.GET }, rootPath, methodPath, MethodHandles.lookup().lookupClass());
        }
    }
}
Also used : GetMapping(org.springframework.web.bind.annotation.GetMapping) Transaction(com.newrelic.agent.bridge.Transaction) PostMapping(org.springframework.web.bind.annotation.PostMapping) DeleteMapping(org.springframework.web.bind.annotation.DeleteMapping) RequestMethod(org.springframework.web.bind.annotation.RequestMethod) PutMapping(org.springframework.web.bind.annotation.PutMapping) PatchMapping(org.springframework.web.bind.annotation.PatchMapping) RequestMapping(org.springframework.web.bind.annotation.RequestMapping) WeaveIntoAllMethods(com.newrelic.api.agent.weaver.WeaveIntoAllMethods) Trace(com.newrelic.api.agent.Trace) WeaveWithAnnotation(com.newrelic.api.agent.weaver.WeaveWithAnnotation)

Example 37 with Transaction

use of com.newrelic.agent.bridge.Transaction in project newrelic-java-agent by newrelic.

the class SpringController_Instrumentation method instrumentation.

@WeaveWithAnnotation(annotationClasses = { "org.springframework.web.bind.annotation.RequestMapping" })
@WeaveIntoAllMethods
@Trace
private static void instrumentation() {
    Transaction transaction = AgentBridge.getAgent().getTransaction(false);
    if (transaction != null) {
        RequestMapping rootPathMapping = Weaver.getClassAnnotation(RequestMapping.class);
        RequestMapping methodPathMapping = Weaver.getMethodAnnotation(RequestMapping.class);
        String rootPath = SpringControllerUtility.getPathValue(rootPathMapping);
        String methodPath = SpringControllerUtility.getPathValue(methodPathMapping);
        RequestMethod httpMethod = RequestMethod.GET;
        RequestMethod[] methods = methodPathMapping.method();
        if (methods.length > 0) {
            httpMethod = methods[0];
        }
        if (rootPath == null && methodPath == null) {
            AgentBridge.getAgent().getLogger().log(Level.FINE, "No path was specified for SpringController {0}", MethodHandles.lookup().lookupClass().getName());
        } else {
            String fullPath = SpringControllerUtility.getPath(rootPath, methodPath, httpMethod);
            transaction.setTransactionName(TransactionNamePriority.FRAMEWORK_HIGH, true, "SpringController", fullPath);
        }
    }
}
Also used : Transaction(com.newrelic.agent.bridge.Transaction) RequestMethod(org.springframework.web.bind.annotation.RequestMethod) RequestMapping(org.springframework.web.bind.annotation.RequestMapping) WeaveIntoAllMethods(com.newrelic.api.agent.weaver.WeaveIntoAllMethods) Trace(com.newrelic.api.agent.Trace) WeaveWithAnnotation(com.newrelic.api.agent.weaver.WeaveWithAnnotation)

Example 38 with Transaction

use of com.newrelic.agent.bridge.Transaction in project newrelic-java-agent by newrelic.

the class TraceClassVisitor method visitMethod.

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
    // skip bridge methods. Tracing will occur on impl method.
    if ((access & Opcodes.ACC_BRIDGE) != 0) {
        /*
             * Some versions of the Agent (mid 3.20.* -> low 3.30.*) had a bug here that caused us to trace bridge
             * methods, resulting in double counting of @Trace'd methods. This bug only affected late versions of JDK7
             * and all versions of JDK8 due to annotations being automatically copied by the JVM over to bridge methods.
             */
        return mv;
    }
    Method method = new Method(name, desc);
    if (traceInfo.getIgnoreTransactionMethods().contains(method)) {
        instrumentationContext.markAsModified();
        return new AdviceAdapter(WeaveUtils.ASM_API_LEVEL, mv, access, name, desc) {

            @Override
            protected void onMethodEnter() {
                BridgeUtils.getCurrentTransaction(this);
                BytecodeGenProxyBuilder.newBuilder(Transaction.class, this, true).build().ignore();
            }
        };
    } else {
        final TraceDetails trace = traceInfo.getTraceAnnotations().get(method);
        if (null != trace) {
            tracedMethods.add(method);
            PointCut pointCut = instrumentationContext.getOldStylePointCut(method);
            if (pointCut == null) {
                boolean custom = trace.isCustom();
                boolean noticeSql = noticeSqlMethods.contains(method);
                if (trace.excludeFromTransactionTrace() && trace.isLeaf()) {
                    mv = new FlyweightTraceMethodVisitor(className, mv, access, name, desc, trace, instrumentationContext.getClassBeingRedefined());
                } else {
                    mv = new TraceMethodVisitor(className, mv, access, name, desc, trace, custom, noticeSql, instrumentationContext.getClassBeingRedefined());
                    if (!trace.getParameterAttributeNames().isEmpty()) {
                        for (ParameterAttributeName attr : trace.getParameterAttributeNames()) {
                            final ParameterAttributeName param = attr;
                            if (param.getMethodMatcher().matches(access, name, desc, null)) {
                                try {
                                    final Type type = method.getArgumentTypes()[param.getIndex()];
                                    if (type.getSort() == Type.ARRAY) {
                                        Agent.LOG.log(Level.FINE, "Unable to record an attribute value for {0}.{1} because it is an array", className, method);
                                    } else {
                                        mv = new AdviceAdapter(WeaveUtils.ASM_API_LEVEL, mv, access, name, desc) {

                                            @Override
                                            protected void onMethodEnter() {
                                                super.getStatic(BridgeUtils.AGENT_BRIDGE_TYPE, BridgeUtils.PUBLIC_API_FIELD_NAME, BridgeUtils.PUBLIC_API_TYPE);
                                                PublicApi api = BytecodeGenProxyBuilder.newBuilder(PublicApi.class, this, false).build();
                                                push(param.getAttributeName());
                                                loadArg(param.getIndex());
                                                // if this is a primitive value we need to box it to an object
                                                if (type.getSort() != Type.OBJECT) {
                                                    box(type);
                                                }
                                                Label objectLabel = newLabel();
                                                Label skipLabel = newLabel();
                                                Label popStackLabel = newLabel();
                                                // dup the value for null check
                                                dup();
                                                ifNull(popStackLabel);
                                                // dup the value for instanceOf check
                                                dup();
                                                instanceOf(Type.getType(Number.class));
                                                ifZCmp(EQ, objectLabel);
                                                // if this is a number, cast it to a number and call the
                                                // addCustomParameter api that takes a number
                                                checkCast(Type.getType(Number.class));
                                                api.addCustomParameter("", 0);
                                                goTo(skipLabel);
                                                visitLabel(objectLabel);
                                                // otherwise, it's a non-null object so call toString
                                                invokeVirtual(Type.getType(Object.class), new Method("toString", Type.getType(String.class), new Type[0]));
                                                api.addCustomParameter("", "");
                                                goTo(skipLabel);
                                                // the values originally on the stack won't be consumed by either
                                                // of the api calls above if the attribute was null
                                                visitLabel(popStackLabel);
                                                pop();
                                                pop();
                                                pop();
                                                visitLabel(skipLabel);
                                            }
                                        };
                                    }
                                } catch (ArrayIndexOutOfBoundsException e) {
                                    Agent.LOG.log(Level.FINEST, e, e.toString());
                                }
                            }
                        }
                    }
                    if (trace.rollupMetricName().length > 0) {
                        final int cacheId = AgentBridge.instrumentation.addToObjectCache(trace.rollupMetricName());
                        mv = new AdviceAdapter(WeaveUtils.ASM_API_LEVEL, mv, access, name, desc) {

                            @Override
                            protected void onMethodEnter() {
                                getStatic(BridgeUtils.TRACED_METHOD_TYPE, BridgeUtils.CURRENT_TRANSACTION_FIELD_NAME, BridgeUtils.TRACED_METHOD_TYPE);
                                super.getStatic(BridgeUtils.AGENT_BRIDGE_TYPE, BridgeUtils.INSTRUMENTATION_FIELD_NAME, BridgeUtils.INSTRUMENTATION_TYPE);
                                Instrumentation instrumentation = BytecodeGenProxyBuilder.newBuilder(Instrumentation.class, this, true).build();
                                instrumentation.getCachedObject(cacheId);
                                super.checkCast(Type.getType(String[].class));
                                TracedMethod tracedMethod = BytecodeGenProxyBuilder.newBuilder(TracedMethod.class, this, false).build();
                                tracedMethod.setRollupMetricNames((String[]) null);
                            }
                        };
                    }
                    if (TransactionName.isSimpleTransactionName(trace.transactionName())) {
                        mv = new AdviceAdapter(WeaveUtils.ASM_API_LEVEL, mv, access, name, desc) {

                            @Override
                            protected void onMethodEnter() {
                                TracedMethod tracedMethod = BytecodeGenProxyBuilder.newBuilder(TracedMethod.class, this, true).build();
                                getStatic(BridgeUtils.TRACED_METHOD_TYPE, BridgeUtils.CURRENT_TRANSACTION_FIELD_NAME, BridgeUtils.TRACED_METHOD_TYPE);
                                tracedMethod.nameTransaction(trace.transactionName().transactionNamePriority);
                            }
                        };
                    } else if (trace.transactionName() != null) {
                        mv = new AdviceAdapter(WeaveUtils.ASM_API_LEVEL, mv, access, name, desc) {

                            @Override
                            protected void onMethodEnter() {
                                BridgeUtils.getCurrentTransaction(this);
                                Transaction transaction = BytecodeGenProxyBuilder.newBuilder(Transaction.class, this, true).build();
                                TransactionName transactionName = trace.transactionName();
                                transaction.setTransactionName(transactionName.transactionNamePriority, transactionName.override, transactionName.category, transactionName.path);
                                // the method returns a boolean. Discard it.
                                pop();
                            }
                        };
                    }
                    if (trace.isWebTransaction()) {
                        mv = new AdviceAdapter(WeaveUtils.ASM_API_LEVEL, mv, access, name, desc) {

                            @Override
                            protected void onMethodExit(int opcode) {
                                getStatic(BridgeUtils.TRANSACTION_TYPE, BridgeUtils.CURRENT_TRANSACTION_FIELD_NAME, BridgeUtils.TRANSACTION_TYPE);
                                BytecodeGenProxyBuilder.newBuilder(Transaction.class, this, true).build().convertToWebTransaction();
                            }
                        };
                    }
                    if (null != trace.metricPrefix()) {
                        mv = new AdviceAdapter(WeaveUtils.ASM_API_LEVEL, mv, access, name, desc) {

                            @Override
                            protected void onMethodExit(int opcode) {
                                // write: AgentBridge.getAgent().getTracedMethod.setMetricPrefix("usersPrefix")
                                this.invokeStatic(BridgeUtils.AGENT_BRIDGE_TYPE, new Method(BridgeUtils.AGENT_BRIDGE_GET_AGENT_METHOD, BridgeUtils.AGENT_BRIDGE_AGENT_TYPE, new Type[0]));
                                this.invokeVirtual(BridgeUtils.AGENT_BRIDGE_AGENT_TYPE, new Method(BridgeUtils.GET_TRACED_METHOD_METHOD_NAME, BridgeUtils.TRACED_METHOD_TYPE, new Type[0]));
                                BytecodeGenProxyBuilder.newBuilder(TracedMethod.class, this, true).build().setCustomMetricPrefix(trace.metricPrefix());
                            }
                        };
                    }
                }
                instrumentationContext.addTimedMethods(method);
            } else {
                Agent.LOG.warning(className + '.' + method + " is matched to trace, but it was already instrumented by " + pointCut.toString());
            }
        }
        if (traceInfo.getIgnoreApdexMethods().contains(method)) {
            instrumentationContext.markAsModified();
            mv = new AdviceAdapter(WeaveUtils.ASM_API_LEVEL, mv, access, name, desc) {

                @Override
                protected void onMethodEnter() {
                    invokeStatic(BridgeUtils.NEW_RELIC_API_TYPE, TraceMethodVisitor.IGNORE_APDEX_METHOD);
                }
            };
        }
    }
    return mv;
}
Also used : Label(org.objectweb.asm.Label) Instrumentation(com.newrelic.agent.bridge.Instrumentation) TracedMethod(com.newrelic.agent.bridge.TracedMethod) Method(org.objectweb.asm.commons.Method) MethodVisitor(org.objectweb.asm.MethodVisitor) PointCut(com.newrelic.agent.instrumentation.PointCut) AdviceAdapter(org.objectweb.asm.commons.AdviceAdapter) Type(org.objectweb.asm.Type) Transaction(com.newrelic.agent.bridge.Transaction) TracedMethod(com.newrelic.agent.bridge.TracedMethod) PublicApi(com.newrelic.agent.bridge.PublicApi)

Example 39 with Transaction

use of com.newrelic.agent.bridge.Transaction in project newrelic-java-agent by newrelic.

the class FlyweightTraceMethodVisitor method onEveryExit.

/**
 * This code is injected at every exit instruction, whether a return or an ATHROW.
 *
 * @see Transaction#finishFlyweightTracer(TracedMethod, long, long, String, String, String, String, String[])
 */
private void onEveryExit() {
    Label skip = super.newLabel();
    super.loadLocal(parentTracerLocal);
    super.ifNull(skip);
    BridgeUtils.getCurrentTransactionOrNull(this);
    super.ifNull(skip);
    BridgeUtils.getCurrentTransaction(this);
    BytecodeGenProxyBuilder<Transaction> builder = BytecodeGenProxyBuilder.newBuilder(Transaction.class, this, true);
    Variables loader = builder.getVariables();
    String[] rollupMetricNames;
    if (rollupMetricNamesCacheId >= 0) {
        rollupMetricNames = loader.load(String[].class, new Runnable() {

            @Override
            public void run() {
                getStatic(BridgeUtils.AGENT_BRIDGE_TYPE, BridgeUtils.INSTRUMENTATION_FIELD_NAME, BridgeUtils.INSTRUMENTATION_TYPE);
                BytecodeGenProxyBuilder.newBuilder(Instrumentation.class, FlyweightTraceMethodVisitor.this, true).build().getCachedObject(rollupMetricNamesCacheId);
                checkCast(Type.getType(String[].class));
            }
        });
    } else {
        rollupMetricNames = null;
    }
    // -1 and -2 are identifiers that tell the ApiBuilder's proxy to (-1) load a local variable and (-2) call
    // System.nanoTime when those values are
    // encountered
    long startTime = loader.loadLocal(startTimeLocal, Type.LONG_TYPE, -1L);
    long loadEndTime = loader.load(-2l, new Runnable() {

        @Override
        public void run() {
            invokeStatic(Type.getType(System.class), new Method("nanoTime", Type.LONG_TYPE, new Type[0]));
        }
    });
    Transaction transactionApi = builder.build();
    transactionApi.finishFlyweightTracer(loader.loadLocal(parentTracerLocal, TracedMethod.class), startTime, loadEndTime, className, this.method.getName(), this.methodDesc, loader.loadLocal(metricNameLocal, String.class), rollupMetricNames);
    super.visitLabel(skip);
}
Also used : Variables(com.newrelic.agent.util.asm.Variables) Transaction(com.newrelic.agent.bridge.Transaction) Label(org.objectweb.asm.Label) TracedMethod(com.newrelic.agent.bridge.TracedMethod) Method(org.objectweb.asm.commons.Method) TracedMethod(com.newrelic.agent.bridge.TracedMethod)

Example 40 with Transaction

use of com.newrelic.agent.bridge.Transaction in project newrelic-java-agent by newrelic.

the class AgentImplTest method testAsyncTracerShouldNotStartTxn.

@Test
public void testAsyncTracerShouldNotStartTxn() {
    TransactionActivity txa = TransactionActivity.create(null, 0);
    ClassMethodSignature sig = new ClassMethodSignature("class", "method", "methodDesc");
    OtherRootTracer tracer = new OtherRootTracer(txa, sig, null, null, TracerFlags.ASYNC, System.nanoTime());
    txa.tracerStarted(tracer);
    Transaction txn = agentImpl.getTransaction();
    Assert.assertTrue(txn instanceof NoOpTransaction);
    Assert.assertFalse(txn instanceof com.newrelic.agent.Transaction);
}
Also used : ClassMethodSignature(com.newrelic.agent.tracers.ClassMethodSignature) Transaction(com.newrelic.agent.bridge.Transaction) NoOpTransaction(com.newrelic.agent.bridge.NoOpTransaction) NoOpTransaction(com.newrelic.agent.bridge.NoOpTransaction) OtherRootTracer(com.newrelic.agent.tracers.OtherRootTracer) Test(org.junit.Test)

Aggregations

Transaction (com.newrelic.agent.bridge.Transaction)40 Trace (com.newrelic.api.agent.Trace)18 TracedMethod (com.newrelic.agent.bridge.TracedMethod)7 AgentBridge (com.newrelic.agent.bridge.AgentBridge)4 WeaveIntoAllMethods (com.newrelic.api.agent.weaver.WeaveIntoAllMethods)4 WeaveWithAnnotation (com.newrelic.api.agent.weaver.WeaveWithAnnotation)4 URI (java.net.URI)4 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4 Segment (com.newrelic.api.agent.Segment)3 Label (org.objectweb.asm.Label)3 Method (org.objectweb.asm.commons.Method)3 TracedMethod (com.newrelic.api.agent.TracedMethod)2 MuleHttpConnectorRequest (com.nr.agent.instrumentation.mule3.MuleHttpConnectorRequest)2 OutboundWrapper (com.nr.instrumentation.jersey.client.OutboundWrapper)2 IOException (java.io.IOException)2 URISyntaxException (java.net.URISyntaxException)2 GET (javax.ws.rs.GET)2 HEAD (javax.ws.rs.HEAD)2 PUT (javax.ws.rs.PUT)2 Test (org.junit.Test)2