use of com.newrelic.agent.tracers.Tracer in project newrelic-java-agent by newrelic.
the class InstrumentationImpl method oldCreateSqlTracer.
// This code path is similar to the 3.16.1 and earlier tracer creation path. It is retained for use by legacy
// async instrumentation, including NAPS (Netty, Akka, Play, Scala) and async servlet instrumentation.
private ExitTracer oldCreateSqlTracer(TransactionActivity txa, Object invocationTarget, int signatureId, String metricName, int flags) {
if (txa == null) {
AgentBridge.TokenAndRefCount tokenAndRefCount = AgentBridge.activeToken.get();
if (tokenAndRefCount != null && tokenAndRefCount.token != null) {
// Fast path for scala instrumentation (and potentially others in the future)
Transaction tx = Transaction.getTransaction(false);
if (tx == null) {
if (tokenAndRefCount.token.getTransaction() instanceof Transaction) {
tx = (Transaction) tokenAndRefCount.token.getTransaction();
} else {
return null;
}
}
txa = TransactionActivity.create(tx, Integer.MAX_VALUE);
flags = flags | TracerFlags.ASYNC;
ClassMethodSignature sig = ClassMethodSignatures.get().get(signatureId);
MetricNameFormat mnf = MetricNameFormats.getFormatter(invocationTarget, sig, metricName, flags);
Tracer tracer;
if (TracerFlags.isRoot(flags)) {
// Dispatcher || Async
tracer = new OtherRootSqlTracer(txa, sig, invocationTarget, mnf, flags);
} else if (overSegmentLimit(txa)) {
logger.log(Level.FINEST, "Transaction has exceeded tracer segment limit. Returning ultralight sql tracer.");
return UltraLightTracer.createClampedSegment(txa, sig);
} else {
tracer = new DefaultSqlTracer(txa, sig, invocationTarget, mnf, flags);
}
txa.tracerStarted(tracer);
Tracer initiatingTracer = (Tracer) tokenAndRefCount.tracedMethod.getAndSet(tracer);
tx.startFastAsyncWork(txa, initiatingTracer);
return tracer;
} else if (TracerFlags.isAsync(flags)) {
txa = TransactionActivity.create(null, Integer.MAX_VALUE);
return startTracer(txa, invocationTarget, signatureId, metricName, flags);
}
}
// Avoid creating tracers for NoOpTransaction, etc.
com.newrelic.agent.Transaction transaction = com.newrelic.agent.Transaction.getTransaction(TracerFlags.isDispatcher(flags));
if (transaction == null) {
return null;
}
try {
if (!TracerFlags.isDispatcher(flags) && !transaction.isStarted()) {
// if we're not in a transaction and this isn't a dispatcher tracer, bail before we create objects
return null;
}
if (transaction.getTransactionActivity().isLeaf()) {
return null;
}
ClassMethodSignature sig = ClassMethodSignatures.get().get(signatureId);
return transaction.getTransactionState().getSqlTracer(transaction, invocationTarget, sig, metricName, flags);
} catch (Throwable t) {
logger.log(Level.FINEST, t, "createTracer({0}, {1}, {2}, {3})", invocationTarget, signatureId, metricName, flags);
return null;
}
}
use of com.newrelic.agent.tracers.Tracer in project newrelic-java-agent by newrelic.
the class InstrumentationImpl method startTracer.
// Preconditions are met: start a new tracer on this thread. There may not be a Transaction on this thread. Code
// in this path MUST NOT attempt to touch the Transaction or do anything that might bring one into existence. This
// inconvenience is absolutely critical to the performance of our async instrumentation.
private Tracer startTracer(TransactionActivity txa, Object target, int signatureId, String metricName, int flags) {
ClassMethodSignature sig = ClassMethodSignatures.get().get(signatureId);
MetricNameFormat mnf = MetricNameFormats.getFormatter(target, sig, metricName, flags);
Tracer tracer;
if (TracerFlags.isRoot(flags)) {
// Dispatcher || Async
tracer = new OtherRootTracer(txa, sig, target, mnf, flags, System.nanoTime());
} else {
tracer = new DefaultTracer(txa, sig, target, mnf, flags);
}
txa.tracerStarted(tracer);
return tracer;
}
use of com.newrelic.agent.tracers.Tracer in project newrelic-java-agent by newrelic.
the class TransactionProfile method buildChildren.
public static Map<Tracer, Collection<Tracer>> buildChildren(Collection<Tracer> tracers, List<List<StackTraceElement>> backtraces) {
if (tracers == null || tracers.isEmpty()) {
return Collections.emptyMap();
}
Map<Tracer, Collection<Tracer>> children = new HashMap<>();
for (Tracer tracer : tracers) {
@SuppressWarnings("unchecked") List<StackTraceElement> backtrace = (List<StackTraceElement>) tracer.getAgentAttribute(DefaultTracer.BACKTRACE_PARAMETER_NAME);
if (null != backtrace) {
backtraces.add(backtrace);
}
Tracer parentTracer = tracer.getParentTracer();
Collection<Tracer> kids = children.get(parentTracer);
if (kids == null) {
kids = new ArrayList<>(parentTracer == null ? 1 : Math.max(1, parentTracer.getChildCount()));
children.put(parentTracer, kids);
}
kids.add(tracer);
}
return children;
}
use of com.newrelic.agent.tracers.Tracer in project newrelic-java-agent by newrelic.
the class TransactionProfile method transactionFinished.
public void transactionFinished(TransactionData transactionData) {
final List<MetricNameTime> cpuTimes = new ArrayList<>();
for (TransactionActivity activity : transactionData.getTransactionActivities()) {
ThreadInfo threadInfo = threadMXBean.getThreadInfo(activity.getThreadId(), 0);
if (null != threadInfo) {
final List<List<StackTraceElement>> backtraces = new ArrayList<>();
Map<Tracer, Collection<Tracer>> tracerTree = buildChildren(activity.getTracers(), backtraces);
String threadName = threadNameNormalizer.getNormalizedThreadName(new BasicThreadInfo(threadInfo));
threadActivityProfiles.get(threadName).add(activity, tracerTree);
if (!backtraces.isEmpty()) {
ProfileTree tree = threadProfiles.get(threadName);
for (List<StackTraceElement> stack : backtraces) {
stack = DiscoveryProfile.getScrubbedStackTrace(stack);
Collections.reverse(stack);
tree.addStackTrace(stack, true);
}
}
long cpuTime = activity.getTotalCpuTime();
if (cpuTime > 0) {
MetricName name = MetricName.create(transactionData.getBlameMetricName(), threadName);
cpuTimes.add(new MetricNameTime(name, cpuTime));
}
}
}
if (!cpuTimes.isEmpty()) {
ServiceFactory.getStatsService().doStatsWork(new StatsWork() {
@Override
public void doWork(StatsEngine statsEngine) {
for (MetricNameTime time : cpuTimes) {
statsEngine.getResponseTimeStats(time.name).recordResponseTime(time.cpuTime, TimeUnit.NANOSECONDS);
}
}
@Override
public String getAppName() {
return null;
}
}, transactionData.getBlameMetricName());
}
}
use of com.newrelic.agent.tracers.Tracer in project newrelic-java-agent by newrelic.
the class TransactionTrace method createTransactionSegment.
private TransactionSegment createTransactionSegment(TransactionTracerConfig ttConfig, SqlObfuscator sqlObfuscator, Tracer tracer, TransactionSegment lastSibling) {
TransactionSegment segment = tracer.getTransactionSegment(ttConfig, sqlObfuscator, rootTracerStartTime, lastSibling);
processSqlTracer(tracer);
Collection<Tracer> children = this.children.get(tracer);
if (children != null) {
TransactionSegment lastKid = null;
for (Tracer child : children) {
if (child.getTransactionSegmentName() != null) {
TransactionSegment childSegment = createTransactionSegment(ttConfig, sqlObfuscator, child, lastKid);
if (childSegment != lastKid) {
/*
* We used to check the childSegment's metric name for null and remove it if the name was null.
* After reading the code and writing a test, I do not think it is possible to have a null
* metric name. The transaction segment code sets it to the tracer class if it is null. I have
* no clue why we would ever want to send up a segment with the tracer class as the name.
*/
segment.addChild(childSegment);
lastKid = childSegment;
}
}
}
}
return segment;
}
Aggregations