Search in sources :

Example 1 with PublicApi

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

the class CustomExtensionTestAddition method testRecordObjectParam.

@Test
@Trace(dispatcher = true)
public void testRecordObjectParam() throws Exception {
    PublicApi original = AgentBridge.publicApi;
    PublicApi api = Mockito.mock(PublicApi.class);
    AgentBridge.publicApi = api;
    try {
        MimeType sample = new MimeType();
        sample.getParameter("recordThis");
        Mockito.verify(api).addCustomParameter("theKey", "recordThis");
    } finally {
        AgentBridge.publicApi = original;
    }
}
Also used : PublicApi(com.newrelic.agent.bridge.PublicApi) MimeType(javax.activation.MimeType) Trace(com.newrelic.api.agent.Trace) Java17IncompatibleTest(com.newrelic.test.marker.Java17IncompatibleTest) Java13IncompatibleTest(com.newrelic.test.marker.Java13IncompatibleTest) Java16IncompatibleTest(com.newrelic.test.marker.Java16IncompatibleTest) Java14IncompatibleTest(com.newrelic.test.marker.Java14IncompatibleTest) Test(org.junit.Test) Java11IncompatibleTest(com.newrelic.test.marker.Java11IncompatibleTest) Java15IncompatibleTest(com.newrelic.test.marker.Java15IncompatibleTest) Java12IncompatibleTest(com.newrelic.test.marker.Java12IncompatibleTest) Java18IncompatibleTest(com.newrelic.test.marker.Java18IncompatibleTest)

Example 2 with PublicApi

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

the class CustomExtensionTest method testRecordPrimitiveParam.

@Test
@Trace(dispatcher = true)
public void testRecordPrimitiveParam() throws Exception {
    PublicApi original = AgentBridge.publicApi;
    PublicApi api = Mockito.mock(PublicApi.class);
    AgentBridge.publicApi = api;
    try {
        new com.newrelic.agent.instrumentation.CustomExtensionTest.ClassToRetransformObject(0).methodWithParams(666);
        Mockito.verify(api).addCustomParameter("dollarz", 666);
    } finally {
        AgentBridge.publicApi = original;
    }
}
Also used : PublicApi(com.newrelic.agent.bridge.PublicApi) Trace(com.newrelic.api.agent.Trace) Test(org.junit.Test)

Example 3 with PublicApi

use of com.newrelic.agent.bridge.PublicApi 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)

Aggregations

PublicApi (com.newrelic.agent.bridge.PublicApi)3 Trace (com.newrelic.api.agent.Trace)2 Test (org.junit.Test)2 Instrumentation (com.newrelic.agent.bridge.Instrumentation)1 TracedMethod (com.newrelic.agent.bridge.TracedMethod)1 Transaction (com.newrelic.agent.bridge.Transaction)1 PointCut (com.newrelic.agent.instrumentation.PointCut)1 Java11IncompatibleTest (com.newrelic.test.marker.Java11IncompatibleTest)1 Java12IncompatibleTest (com.newrelic.test.marker.Java12IncompatibleTest)1 Java13IncompatibleTest (com.newrelic.test.marker.Java13IncompatibleTest)1 Java14IncompatibleTest (com.newrelic.test.marker.Java14IncompatibleTest)1 Java15IncompatibleTest (com.newrelic.test.marker.Java15IncompatibleTest)1 Java16IncompatibleTest (com.newrelic.test.marker.Java16IncompatibleTest)1 Java17IncompatibleTest (com.newrelic.test.marker.Java17IncompatibleTest)1 Java18IncompatibleTest (com.newrelic.test.marker.Java18IncompatibleTest)1 MimeType (javax.activation.MimeType)1 Label (org.objectweb.asm.Label)1 MethodVisitor (org.objectweb.asm.MethodVisitor)1 Type (org.objectweb.asm.Type)1 AdviceAdapter (org.objectweb.asm.commons.AdviceAdapter)1