Search in sources :

Example 11 with TracedMethod

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

the class HttpURLConnection method getResponseCode.

@Trace(leaf = true)
public int getResponseCode() throws Exception {
    MetricState metricState = lazyGetMetricState();
    TracedMethod method = AgentBridge.getAgent().getTracedMethod();
    metricState.getResponseCodePreamble(this, method);
    int responseCodeValue;
    try {
        // This does a network request (if getInputStream() wasn't called first)
        responseCodeValue = Weaver.callOriginal();
    } catch (Exception e) {
        // This is the default legacy behavior of the AbstractExternalComponentTracer
        if (e instanceof UnknownHostException) {
            method.setMetricName("External", "UnknownHost", "HttpURLConnection");
        }
        throw e;
    }
    metricState.getInboundPostamble(this, method);
    return responseCodeValue;
}
Also used : MetricState(com.nr.agent.instrumentation.httpurlconnection.MetricState) TracedMethod(com.newrelic.agent.bridge.TracedMethod) IOException(java.io.IOException) Trace(com.newrelic.api.agent.Trace)

Example 12 with TracedMethod

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

the class HttpMethodBase method execute.

@Trace(leaf = true)
public int execute(HttpState state, HttpConnection conn) throws IOException {
    String host = null;
    String uri = null;
    TracedMethod method = AgentBridge.getAgent().getTracedMethod();
    Transaction tx = AgentBridge.getAgent().getTransaction();
    if (!checkForIgnoredSocketCall(method)) {
        // URI calculation logic migrated from old pointcut to maintain parity
        URI methodURI = getURI();
        String scheme = methodURI.getScheme();
        if (scheme == null) {
            scheme = conn.getProtocol().getScheme();
            host = conn.getHost();
            String path = methodURI.getPath();
            if ("null".equals(path)) {
                path = null;
            }
            uri = URISupport.getURI(scheme, host, conn.getPort(), path);
        } else {
            host = methodURI.getHost();
            uri = URISupport.getURI(methodURI.getScheme(), host, conn.getPort(), methodURI.getPath());
        }
        // Set cross process headers for this outbound request
        method.addOutboundRequestHeaders(new OutboundWrapper(this));
    }
    int responseCode = Weaver.callOriginal();
    if (!checkForIgnoredSocketCall(method) && uri != null) {
        try {
            InboundWrapper inboundHeaders = new InboundWrapper(this);
            java.net.URI netURI = java.net.URI.create(uri);
            method.reportAsExternal(HttpParameters.library(LIBRARY).uri(netURI).procedure("execute").inboundHeaders(inboundHeaders).status(responseCode, this.getStatusText()).build());
        } catch (Throwable e) {
            AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to reportAsExternal for execute()");
        }
    }
    return responseCode;
}
Also used : Transaction(com.newrelic.agent.bridge.Transaction) InboundWrapper(com.nr.agent.instrumentation.httpclient31.InboundWrapper) TracedMethod(com.newrelic.agent.bridge.TracedMethod) OutboundWrapper(com.nr.agent.instrumentation.httpclient31.OutboundWrapper) Trace(com.newrelic.api.agent.Trace)

Example 13 with TracedMethod

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

the class MuleWorkManager_Instrumentation method executeWork.

@Trace
private void executeWork(WorkerContext work, WorkExecutor workExecutor) {
    final Transaction txn = AgentBridge.getAgent().getTransaction(false);
    if (txn != null) {
        TracedMethod tm = (TracedMethod) txn.getTracedMethod();
        if (tm != null) {
            tm.setMetricName("Flow", "MuleWorkManager", "executeWork", name);
        }
    }
    Weaver.callOriginal();
}
Also used : Transaction(com.newrelic.agent.bridge.Transaction) TracedMethod(com.newrelic.agent.bridge.TracedMethod) Trace(com.newrelic.api.agent.Trace)

Example 14 with TracedMethod

use of com.newrelic.agent.bridge.TracedMethod 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 15 with TracedMethod

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

the class FlyweightTraceMethodVisitor method getTracedMethodMethodHandlers.

/**
 * Creates handlers responsible for generating the bytecode that replaces invocations of all {@link TracedMethod}
 * methods.
 *
 * @see TracedMethod
 */
private Map<Method, Handler> getTracedMethodMethodHandlers() {
    Map<Method, Handler> map = new HashMap<>();
    map.put(new Method("getMetricName", "()Ljava/lang/String;"), new Handler() {

        @Override
        public void handle(AdviceAdapter mv) {
            mv.loadLocal(metricNameLocal);
        }
    });
    map.put(new Method("setMetricName", "([Ljava/lang/String;)V"), new Handler() {

        @Override
        public void handle(AdviceAdapter mv) {
            // this one is a little tricky because an array is on the stack. We need to concat it to a string
            // Joiner.on("").join(parts);
            mv.checkCast(Type.getType(Object[].class));
            push("");
            mv.invokeStatic(JOINER_TYPE, new Method("on", JOINER_TYPE, new Type[] { Type.getType(String.class) }));
            mv.swap();
            mv.invokeVirtual(JOINER_TYPE, new Method("join", Type.getType(String.class), new Type[] { Type.getType(Object[].class) }));
            mv.storeLocal(metricNameLocal);
        }
    });
    addUnsupportedMethod(map, new Method("nameTransaction", Type.VOID_TYPE, new Type[] { Type.getType(TransactionNamePriority.class) }));
    addUnsupportedMethod(map, new Method("setRollupMetricNames", "([Ljava/lang/String;)V"));
    addUnsupportedMethod(map, new Method("addRollupMetricName", "([Ljava/lang/String;)V"));
    addUnsupportedMethod(map, new Method("setMetricNameFormatInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"));
    addUnsupportedMethod(map, new Method("addExclusiveRollupMetricName", "([Ljava/lang/String;)V"));
    addUnsupportedMethod(map, new Method("isMetricProducer", "()Z"));
    addUnsupportedMethod(map, new Method("setCustomMetricPrefix", "(Ljava/lang/String;)V"));
    addUnsupportedMethod(map, new Method("setTrackChildThreads", "(Z)V"));
    addUnsupportedMethod(map, new Method("trackChildThreads", "()Z"));
    addUnsupportedMethod(map, new Method("setTrackCallbackRunnable", "(Z)V"));
    addUnsupportedMethod(map, new Method("isTrackCallbackRunnable", "()Z"));
    addUnsupportedMethod(map, new Method("reportAsDatastore", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"));
    addUnsupportedMethod(map, new Method("addOutboundRequestHeaders", "(Lcom/newrelic/api/agent/OutboundHeaders;)V"));
    addUnsupportedMethod(map, new Method("readInboundResponseHeaders", "(Lcom/newrelic/api/agent/InboundHeaders;)V"));
    addUnsupportedMethod(map, new Method("reportAsExternal", "(Lcom/newrelic/agent/bridge/external/ExternalParameters;)V"));
    addUnsupportedMethod(map, new Method("reportAsExternal", "(Lcom/newrelic/api/agent/ExternalParameters;)V"));
    addUnsupportedMethod(map, new Method("addCustomAttribute", "(Ljava/lang/String;Ljava/lang/String;)V"));
    addUnsupportedMethod(map, new Method("addCustomAttribute", "(Ljava/lang/String;Ljava/lang/Number;)V"));
    addUnsupportedMethod(map, new Method("addCustomAttribute", "(Ljava/lang/String;Z)V"));
    addUnsupportedMethod(map, new Method("addCustomAttributes", "(Ljava/util/Map;)V"));
    map.put(new Method("getParentTracedMethod", "()Lcom/newrelic/agent/bridge/TracedMethod;"), new Handler() {

        @Override
        public void handle(AdviceAdapter mv) {
            mv.loadLocal(parentTracerLocal);
        }
    });
    return map;
}
Also used : AdviceAdapter(org.objectweb.asm.commons.AdviceAdapter) Type(org.objectweb.asm.Type) HashMap(java.util.HashMap) TracedMethod(com.newrelic.agent.bridge.TracedMethod) Method(org.objectweb.asm.commons.Method)

Aggregations

TracedMethod (com.newrelic.agent.bridge.TracedMethod)16 Trace (com.newrelic.api.agent.Trace)8 Transaction (com.newrelic.agent.bridge.Transaction)6 Test (org.junit.Test)4 Method (org.objectweb.asm.commons.Method)4 ExitTracer (com.newrelic.agent.bridge.ExitTracer)2 DefaultTracer (com.newrelic.agent.tracers.DefaultTracer)2 OtherRootTracer (com.newrelic.agent.tracers.OtherRootTracer)2 Tracer (com.newrelic.agent.tracers.Tracer)2 MetricState (com.nr.agent.instrumentation.httpurlconnection.MetricState)2 IOException (java.io.IOException)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 Label (org.objectweb.asm.Label)2 Type (org.objectweb.asm.Type)2 AdviceAdapter (org.objectweb.asm.commons.AdviceAdapter)2 Instrumentation (com.newrelic.agent.bridge.Instrumentation)1 PublicApi (com.newrelic.agent.bridge.PublicApi)1 TracedActivity (com.newrelic.agent.bridge.TracedActivity)1 PointCut (com.newrelic.agent.instrumentation.PointCut)1 Variables (com.newrelic.agent.util.asm.Variables)1