use of com.newrelic.agent.stats.TransactionStats in project newrelic-java-agent by newrelic.
the class Transaction method finishTransaction.
private void finishTransaction() {
try {
synchronized (lock) {
// this may have the side-effect of ignoring the transaction
freezeTransactionName();
if (ignore) {
Agent.LOG.log(Level.FINER, "Transaction {0} was cancelled: ignored. This is not an error condition.", this);
ServiceFactory.getTransactionService().transactionCancelled(this);
return;
}
if (finishedChildren.isEmpty()) {
Agent.LOG.log(Level.FINER, "Transaction {0} was cancelled: no activities. This is not an error condition.", this);
ServiceFactory.getTransactionService().transactionCancelled(this);
return;
}
// this needs to go before dispatcher.transactionFinished so that all of
// the time metrics are correct
TransactionStats transactionStats = transactionFinishedActivityMerging();
transactionTime.markTransactionAsDone();
recordFinalGCTime(transactionStats);
handleTokenTimeout(transactionStats);
String txName = priorityTransactionName.getName();
// parse headers in dispatcher request before we get rid of request/response objects
getInboundHeaderState();
// this may trigger this dispatcher to record extra metrics like apdex & HttpDispatcher
dispatcher.transactionFinished(txName, transactionStats);
if (Agent.LOG.isFinerEnabled()) {
String requestURI = dispatcher == null ? "No Dispatcher Defined" : dispatcher.getUri();
Agent.LOG.log(Level.FINER, "Transaction {0} for request: {1} finished {2}ms {3}", txName, requestURI, transactionTime.getResponseTimeInMilliseconds(), this);
}
if (!ServiceFactory.getServiceManager().isStarted()) {
Agent.LOG.log(Level.INFO, "Transaction {0} tried to finish but ServiceManager not started", this);
return;
}
// Some parts of the code below are only required if this transaction's TT is selected
// for sending upstream. Unfortunately we don't know at this point in the harvest whether
// this transaction's trace will be selected, and there's no obvious way to know that can
// be built with maintainable code. There was a previous effort at this, but the obvious
// happened: it sat broken in the code (i.e. it did some checks, but always returned true)
// for 18 months before we noticed and ripped it out. Please don't repeat this mistake.
TransactionTracerConfig ttConfig = getTransactionTracerConfig();
TransactionCounts rootCounts = getTransactionCounts();
if (rootCounts.isOverTracerSegmentLimit()) {
getIntrinsicAttributes().put(AttributeNames.SEGMENT_CLAMP, rootCounts.getSegmentCount());
// Record supportability metric to track when a segment clamp occurs
transactionStats.getUnscopedStats().getStats(MetricNames.SUPPORTABILITY_TRANSACTION_SEGMENT_CLAMP).recordDataPoint(rootCounts.getSegmentCount());
}
if (rootCounts.isOverTransactionSize()) {
getIntrinsicAttributes().put(AttributeNames.SIZE_LIMIT_PARAMETER_NAME, "The transaction size limit was reached");
}
int count = rootCounts.getStackTraceCount();
if (count >= ttConfig.getMaxStackTraces()) {
getIntrinsicAttributes().put(AttributeNames.STACK_TRACE_CLAMP, count);
}
if (rootCounts.isOverTokenLimit()) {
getIntrinsicAttributes().put(AttributeNames.TOKEN_CLAMP, rootCounts.getTokenCount());
}
count = rootCounts.getExplainPlanCount();
if (count >= ttConfig.getMaxExplainPlans()) {
getIntrinsicAttributes().put(AttributeNames.EXPLAIN_PLAN_CLAMP, count);
}
DistributedTracingConfig distributedTracingConfig = getAgentConfig().getDistributedTracingConfig();
if (!distributedTracingConfig.isEnabled()) {
if (getInboundHeaderState().isTrustedCatRequest()) {
String id = getInboundHeaderState().getClientCrossProcessId();
getIntrinsicAttributes().put(AttributeNames.CLIENT_CROSS_PROCESS_ID_PARAMETER_NAME, id);
}
String referrerGuid = getInboundHeaderState().getReferrerGuid();
if (referrerGuid != null) {
getIntrinsicAttributes().put(AttributeNames.REFERRING_TRANSACTION_TRACE_ID_PARAMETER_NAME, referrerGuid);
}
String tripId = getCrossProcessTransactionState().getTripId();
if (tripId != null) {
getIntrinsicAttributes().put(AttributeNames.TRIP_ID_PARAMETER_NAME, tripId);
int pathHash = getCrossProcessTransactionState().generatePathHash();
getIntrinsicAttributes().put(AttributeNames.PATH_HASH_PARAMETER_NAME, ServiceUtils.intToHexString(pathHash));
}
}
if (isSynthetic()) {
Agent.LOG.log(Level.FINEST, "Completing Synthetics transaction for monitor {0}", getInboundHeaderState().getSyntheticsMonitorId());
getIntrinsicAttributes().put(AttributeNames.SYNTHETICS_RESOURCE_ID, this.getInboundHeaderState().getSyntheticsResourceId());
getIntrinsicAttributes().put(AttributeNames.SYNTHETICS_MONITOR_ID, this.getInboundHeaderState().getSyntheticsMonitorId());
getIntrinsicAttributes().put(AttributeNames.SYNTHETICS_JOB_ID, this.getInboundHeaderState().getSyntheticsJobId());
}
if (timeoutCause != null && timeoutCause.cause != null) {
getIntrinsicAttributes().put(AttributeNames.TIMEOUT_CAUSE, timeoutCause.cause);
}
String displayHost = getAgentConfig().getValue("process_host.display_name", null);
if (displayHost != null) {
getAgentAttributes().put(AttributeNames.DISPLAY_HOST, displayHost);
}
String instanceName = ServiceFactory.getEnvironmentService().getEnvironment().getAgentIdentity().getInstanceName();
if (instanceName != null) {
getAgentAttributes().put(AttributeNames.INSTANCE_NAME, instanceName);
}
// Only add jvm.thread_name if transaction was not timed out and
// if it's *NOT* a multi-threaded transaction
TimedSet<TokenImpl> tokenCache = activeTokensCache.get();
if ((tokenCache == null || tokenCache.timedOutCount() == 0) && finishedChildren.size() == 1) {
if (!ServiceFactory.getThreadService().isAgentThreadId(Thread.currentThread().getId())) {
getAgentAttributes().put(AttributeNames.THREAD_NAME, Thread.currentThread().getName());
}
}
getIntrinsicAttributes().put(AttributeNames.PRIORITY, getPriority());
TransactionData transactionData = new TransactionData(this, rootCounts.getTransactionSize());
ServiceFactory.getTransactionService().transactionFinished(transactionData, transactionStats);
}
} catch (Throwable th) {
Agent.LOG.log(Level.WARNING, th, "Transaction {0} was not reported because of an internal error.", this);
ServiceFactory.getTransactionService().transactionCancelled(this);
}
}
use of com.newrelic.agent.stats.TransactionStats in project newrelic-java-agent by newrelic.
the class Transaction method activityFinished.
public void activityFinished(TransactionActivity activity, Tracer tracer, int opcode) {
Agent.LOG.log(Level.FINER, "Transaction {0}: Activity {1} finished with opcode {2}", this, activity, opcode);
synchronized (lock) {
try {
if (!isFinished()) {
// we are assuming if you call this, you are part of the transaction
if (!tracer.isTransactionSegment()) {
/*
* If the root tracer is not a transaction segment then there should not be any tracers in the
* txa. It also means we do not need to store the txa for the transaction trace. We just need to
* port over metrics. The consequence of this is that you will no longer be able to ignore this
* txa once it is finished.
*/
if (txStats == null) {
txStats = activity.getTransactionStats();
} else {
TransactionStats toMergeStats = activity.getTransactionStats();
txStats.getScopedStats().mergeStats(toMergeStats.getScopedStats());
txStats.getUnscopedStats().mergeStats(toMergeStats.getUnscopedStats());
}
} else {
finishedChildren.add(activity);
}
checkFinishTransaction(activity);
}
} finally {
if (!activity.isNotInThreadLocal()) {
transactionHolder.remove();
}
}
}
}
use of com.newrelic.agent.stats.TransactionStats in project newrelic-java-agent by newrelic.
the class TransactionServiceTest method testDispatcherTransactionFinished.
@Test
public void testDispatcherTransactionFinished() {
final AtomicReference<Transaction> finishedTransaction = new AtomicReference<>(null);
final AtomicReference<Transaction> finishedTransactionExtended = new AtomicReference<>(null);
ServiceFactory.getTransactionService().addTransactionListener(new ExtendedTransactionListener() {
@Override
public void dispatcherTransactionStarted(Transaction transaction) {
}
@Override
public void dispatcherTransactionCancelled(Transaction transaction) {
}
@Override
public void dispatcherTransactionFinished(TransactionData transactionData, TransactionStats transactionStats) {
finishedTransactionExtended.set(transactionData.getTransaction());
}
});
ServiceFactory.getTransactionService().addTransactionListener(new TransactionListener() {
@Override
public void dispatcherTransactionFinished(TransactionData transactionData, TransactionStats transactionStats) {
finishedTransaction.set(transactionData.getTransaction());
}
});
Tracer tracer = makeTransaction();
tracer.finish(0, null);
tracer.getParentTracer().finish(0, null);
assertNotNull(tracer);
assertNotNull(finishedTransaction.get());
assertNotNull(finishedTransactionExtended.get());
assertEquals(tracer.getTransactionActivity().getTransaction(), finishedTransaction.get());
assertEquals(tracer.getTransactionActivity().getTransaction(), finishedTransactionExtended.get());
}
use of com.newrelic.agent.stats.TransactionStats in project newrelic-java-agent by newrelic.
the class TransactionDataList method clone.
private TransactionStats clone(TransactionStats transactionStats) throws CloneNotSupportedException {
TransactionStats stats = new TransactionStats();
clone(transactionStats.getScopedStats(), stats.getScopedStats());
clone(transactionStats.getUnscopedStats(), stats.getUnscopedStats());
return stats;
}
use of com.newrelic.agent.stats.TransactionStats in project newrelic-java-agent by newrelic.
the class DefaultSqlTracerTest method testSpanEventDatastoreTruncationAtExactLimit.
@Test
public void testSpanEventDatastoreTruncationAtExactLimit() throws SQLException {
final Connection connection = mock(Connection.class);
DatastoreInstanceDetection.detectConnectionAddress();
DatastoreInstanceDetection.associateAddress(connection, new InetSocketAddress("dbserver.nerd.us", 9945));
DatastoreInstanceDetection.stopDetectingConnectionAddress();
String longQueryString = "SELECT price, name FROM BOOKS WHERE name = " + Strings.repeat("a", 1957);
DefaultSqlTracer tracer = newInstanceDBTracer(longQueryString, connection, "MySQL", "mysql");
tracer.finish(Opcodes.ARETURN, new DummyResultSet());
SpanEventsService spanEventService = ServiceFactory.getSpanEventService();
((SpanEventsServiceImpl) spanEventService).dispatcherTransactionFinished(new TransactionData(tracer.getTransaction(), 1024), new TransactionStats());
SamplingPriorityQueue<SpanEvent> eventPool = spanEventService.getOrCreateDistributedSamplingReservoir(APP_NAME);
List<SpanEvent> spanEvents = eventPool.asList();
assertNotNull(spanEvents);
assertEquals(1, spanEvents.size());
SpanEvent spanEvent = Iterables.getFirst(spanEvents, null);
assertNotNull(spanEvent);
assertEquals("datastore", spanEvent.getIntrinsics().get("category"));
assertEquals("MySQL", spanEvent.getIntrinsics().get("component"));
assertEquals("dbserver.nerd.us", spanEvent.getIntrinsics().get("peer.hostname"));
assertEquals("dbserver.nerd.us:9945", spanEvent.getIntrinsics().get("peer.address"));
assertEquals(2000, spanEvent.getIntrinsics().get("db.statement").toString().length());
// Should not end with ... since it's exactly at the limit
assertTrue(spanEvent.getIntrinsics().get("db.statement").toString().endsWith("aaa"));
assertEquals("books", spanEvent.getIntrinsics().get("db.collection"));
assertEquals("client", spanEvent.getIntrinsics().get("span.kind"));
assertEquals("Datastore/statement/MySQL/books/select", spanEvent.getName());
assertNotNull(spanEvent.getTraceId());
assertNotNull(spanEvent.getGuid());
}
Aggregations