Search in sources :

Example 1 with TraceDetails

use of com.newrelic.agent.instrumentation.tracing.TraceDetails in project newrelic-java-agent by newrelic.

the class FinalClassTransformer method addModifiedMethodAnnotation.

private ClassVisitor addModifiedMethodAnnotation(ClassVisitor cv, final InstrumentationContext context, final ClassLoader loader) {
    return new ClassVisitor(WeaveUtils.ASM_API_LEVEL, cv) {

        private String className;

        @Override
        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
            className = name;
            super.visit(version, access, name, signature, superName, interfaces);
        }

        /**
         * @see InstrumentedMethod#instrumentationTypes()
         * @see InstrumentedMethod#instrumentationNames()
         * @see InstrumentedMethod#dispatcher()
         */
        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
            Method method = new Method(name, desc);
            if (context.isModified(method)) {
                if (loader != null) {
                    TraceDetails traceDetails = context.getTraceInformation().getTraceAnnotations().get(method);
                    boolean dispatcher = false;
                    if (traceDetails != null) {
                        dispatcher = traceDetails.dispatcher();
                    }
                    AnnotationVisitor av = mv.visitAnnotation(Type.getDescriptor(InstrumentedMethod.class), true);
                    av.visit("dispatcher", dispatcher);
                    List<String> instrumentationNames = new ArrayList<>();
                    List<InstrumentationType> instrumentationTypes = new ArrayList<>();
                    Level logLevel = Level.FINER;
                    if (traceDetails != null) {
                        if (traceDetails.instrumentationSourceNames() != null) {
                            instrumentationNames.addAll(traceDetails.instrumentationSourceNames());
                        }
                        if (traceDetails.instrumentationTypes() != null) {
                            for (InstrumentationType type : traceDetails.instrumentationTypes()) {
                                instrumentationTypes.add(type);
                            }
                        }
                        if (traceDetails.isCustom()) {
                            logLevel = Level.FINE;
                        }
                    }
                    PointCut pointCut = context.getOldStylePointCut(method);
                    if (pointCut != null) {
                        instrumentationNames.add(pointCut.getClass().getName());
                        instrumentationTypes.add(InstrumentationType.Pointcut);
                    }
                    Collection<String> instrumentationPackages = context.getMergeInstrumentationPackages(method);
                    if (instrumentationPackages != null && !instrumentationPackages.isEmpty()) {
                        for (String current : instrumentationPackages) {
                            instrumentationNames.add(current);
                            instrumentationTypes.add(InstrumentationType.WeaveInstrumentation);
                        }
                    }
                    if (instrumentationNames.size() == 0) {
                        instrumentationNames.add("Unknown");
                        Agent.LOG.finest("Unknown instrumentation source for " + className + '.' + method);
                    }
                    if (instrumentationTypes.size() == 0) {
                        instrumentationTypes.add(InstrumentationType.Unknown);
                        Agent.LOG.finest("Unknown instrumentation type for " + className + '.' + method);
                    }
                    AnnotationVisitor visitArrayName = av.visitArray("instrumentationNames");
                    for (String current : instrumentationNames) {
                        // the key on this is ignored
                        visitArrayName.visit("", current);
                    }
                    visitArrayName.visitEnd();
                    AnnotationVisitor visitArrayType = av.visitArray("instrumentationTypes");
                    for (InstrumentationType type : instrumentationTypes) {
                        // the key on this is ignored
                        visitArrayType.visitEnum("", Type.getDescriptor(InstrumentationType.class), type.toString());
                    }
                    visitArrayType.visitEnd();
                    av.visitEnd();
                    if (Agent.LOG.isLoggable(logLevel)) {
                        Agent.LOG.log(logLevel, "Instrumented " + Type.getObjectType(className).getClassName() + '.' + method + ", " + instrumentationTypes + ", " + instrumentationNames);
                    }
                }
            }
            return mv;
        }
    };
}
Also used : InstrumentationType(com.newrelic.agent.instrumentation.InstrumentationType) ArrayList(java.util.ArrayList) TraceDetails(com.newrelic.agent.instrumentation.tracing.TraceDetails) InstrumentedMethod(com.newrelic.agent.instrumentation.InstrumentedMethod) ClassVisitor(org.objectweb.asm.ClassVisitor) Method(org.objectweb.asm.commons.Method) WeavedMethod(com.newrelic.agent.instrumentation.WeavedMethod) InstrumentedMethod(com.newrelic.agent.instrumentation.InstrumentedMethod) MethodVisitor(org.objectweb.asm.MethodVisitor) PointCut(com.newrelic.agent.instrumentation.PointCut) AnnotationVisitor(org.objectweb.asm.AnnotationVisitor) Level(java.util.logging.Level)

Example 2 with TraceDetails

use of com.newrelic.agent.instrumentation.tracing.TraceDetails in project newrelic-java-agent by newrelic.

the class TraceByReturnTypeMatchVisitor method newClassMatchVisitor.

@Override
public ClassVisitor newClassMatchVisitor(ClassLoader loader, Class<?> classBeingRedefined, final ClassReader reader, ClassVisitor cv, final InstrumentationContext context) {
    return new ClassVisitor(WeaveUtils.ASM_API_LEVEL, cv) {

        private boolean isScalaFutureTrace = false;

        private List<String> traceReturnTypeDescriptors = new ArrayList<>();

        @Override
        public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
            AnnotationVisitor av = super.visitAnnotation(descriptor, visible);
            if (TRACE_BY_RETURN_TYPE_DESC.equals(descriptor)) {
                isScalaFutureTrace = true;
                av = new AnnotationVisitor(WeaveUtils.ASM_API_LEVEL, av) {

                    @Override
                    public AnnotationVisitor visitArray(String name) {
                        AnnotationVisitor av = super.visitArray(name);
                        if (TRACE_RETURN_TYPES_NAME.equals(name)) {
                            return new AnnotationVisitor(WeaveUtils.ASM_API_LEVEL, av) {

                                @Override
                                public void visit(String name, Object value) {
                                    super.visit(name, value);
                                    traceReturnTypeDescriptors.add(((Type) value).getDescriptor());
                                }
                            };
                        }
                        return av;
                    }
                };
            }
            return av;
        }

        @Override
        public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
            if (isScalaFutureTrace && isTracedMethod(descriptor)) {
                Method method = new Method(name, descriptor);
                TraceDetails traceDetails = TraceDetailsBuilder.newBuilder().setMetricName(method.getName()).setInstrumentationType(InstrumentationType.BuiltIn).setInstrumentationSourceName(TraceByReturnType.class.getName()).setTransactionName(TransactionNamePriority.FRAMEWORK_LOW, false, MetricNames.CUSTOM, method.getName()).build();
                context.addTrace(method, traceDetails);
            }
            return mv;
        }

        private boolean isTracedMethod(String descriptor) {
            boolean matchFound = false;
            for (String returnTypeDescriptor : traceReturnTypeDescriptors) {
                if (descriptor.endsWith(returnTypeDescriptor)) {
                    matchFound = true;
                    break;
                }
            }
            return matchFound;
        }
    };
}
Also used : TraceDetails(com.newrelic.agent.instrumentation.tracing.TraceDetails) Method(org.objectweb.asm.commons.Method) TraceByReturnType(com.newrelic.api.agent.TraceByReturnType) TraceByReturnType(com.newrelic.api.agent.TraceByReturnType) InstrumentationType(com.newrelic.agent.instrumentation.InstrumentationType)

Example 3 with TraceDetails

use of com.newrelic.agent.instrumentation.tracing.TraceDetails in project newrelic-java-agent by newrelic.

the class TraceInformation method putTraceAnnotation.

void putTraceAnnotation(Method method, TraceDetails trace) {
    if (traces == null) {
        traces = new HashMap<>();
    } else {
        TraceDetails existing = traces.get(method);
        if (existing != null) {
            Agent.LOG.log(Level.FINEST, "Merging trace details {0} and {1} for method {2}", existing, trace, method);
            trace = TraceDetailsBuilder.merge(existing, trace);
        }
    }
    traces.put(method, trace);
}
Also used : TraceDetails(com.newrelic.agent.instrumentation.tracing.TraceDetails)

Example 4 with TraceDetails

use of com.newrelic.agent.instrumentation.tracing.TraceDetails in project newrelic-java-agent by newrelic.

the class FinalClassTransformer method addSupportabilityMetrics.

// Record that we applied "user" instrumentation to a class. Note: generates metric names based on class
// names. But should not cause a metric explosion because auto-generated classes are filtered by the
// ClassFileTransformer and never reach this point. If a metric explosion originates here, the root cause
// is a failure of our proxy-filtering algorithm.
private void addSupportabilityMetrics(ClassReader reader, String className, InstrumentationContext context) {
    StatsService statsService = ServiceFactory.getStatsService();
    if (statsService != null) {
        for (Method m : context.getTimedMethods()) {
            TraceDetails traceDetails = context.getTraceInformation().getTraceAnnotations().get(m);
            if (traceDetails != null && traceDetails.isCustom()) {
                String metricOrigin = MessageFormat.format(MetricNames.SUPPORTABILITY_INSTRUMENT, className.replace('/', '.'), m.getName(), m.getDescriptor());
                statsService.doStatsWork(StatsWorks.getRecordMetricWork(metricOrigin, 1), metricOrigin);
            }
        }
    }
}
Also used : StatsService(com.newrelic.agent.stats.StatsService) TraceDetails(com.newrelic.agent.instrumentation.tracing.TraceDetails) Method(org.objectweb.asm.commons.Method) WeavedMethod(com.newrelic.agent.instrumentation.WeavedMethod) InstrumentedMethod(com.newrelic.agent.instrumentation.InstrumentedMethod)

Example 5 with TraceDetails

use of com.newrelic.agent.instrumentation.tracing.TraceDetails in project newrelic-java-agent by newrelic.

the class CustomClassTransformer method addMatchesToTraces.

private void addMatchesToTraces(InstrumentationContext pContext, Match match) {
    Collection<ExtensionClassAndMethodMatcher> matches = new ArrayList<>(extensionPointCuts);
    matches.retainAll(match.getClassMatches().keySet());
    if (!matches.isEmpty()) {
        for (ExtensionClassAndMethodMatcher pc : matches) {
            for (Method m : match.getMethods()) {
                if (pc.getMethodMatcher().matches(MethodMatcher.UNSPECIFIED_ACCESS, m.getName(), m.getDescriptor(), match.getMethodAnnotations(m))) {
                    Method method = pContext.getBridgeMethods().get(m);
                    if (method != null) {
                        // we don't want to instrument bridge methods, we want to instrument the typed
                        // implementation because the bridge method will always call the typed implementation
                        // but direct calls to the typed instrumentation won't pass through the bridge method
                        m = method;
                    }
                    TraceDetails td = pc.getTraceDetails();
                    if (td.ignoreTransaction()) {
                        if (LOG.isFinerEnabled()) {
                            LOG.log(Level.FINER, MessageFormat.format("Matched method {0} for ignoring the transaction trace.", m.toString()));
                        }
                        pContext.addIgnoreTransactionMethod(m);
                    } else {
                        if (LOG.isFinerEnabled()) {
                            LOG.log(Level.FINER, MessageFormat.format("Matched method {0} for instrumentation.", m.toString()));
                        }
                        pContext.addTrace(m, td);
                    }
                }
            }
        }
    }
}
Also used : ArrayList(java.util.ArrayList) TraceDetails(com.newrelic.agent.instrumentation.tracing.TraceDetails) Method(org.objectweb.asm.commons.Method)

Aggregations

TraceDetails (com.newrelic.agent.instrumentation.tracing.TraceDetails)5 Method (org.objectweb.asm.commons.Method)4 InstrumentationType (com.newrelic.agent.instrumentation.InstrumentationType)2 InstrumentedMethod (com.newrelic.agent.instrumentation.InstrumentedMethod)2 WeavedMethod (com.newrelic.agent.instrumentation.WeavedMethod)2 ArrayList (java.util.ArrayList)2 PointCut (com.newrelic.agent.instrumentation.PointCut)1 StatsService (com.newrelic.agent.stats.StatsService)1 TraceByReturnType (com.newrelic.api.agent.TraceByReturnType)1 Level (java.util.logging.Level)1 AnnotationVisitor (org.objectweb.asm.AnnotationVisitor)1 ClassVisitor (org.objectweb.asm.ClassVisitor)1 MethodVisitor (org.objectweb.asm.MethodVisitor)1