From c7f05106a733c0557cde1a7eba58cf0da05b23db Mon Sep 17 00:00:00 2001 From: Thomas Spring Date: Thu, 17 Sep 2020 09:18:47 -0700 Subject: [PATCH 1/4] Add addCustomAttribute api to Segment --- .../newrelic/agent/bridge/NoOpSegment.java | 18 ++ .../main/java/com/newrelic/agent/Segment.java | 38 +++- .../java/com/newrelic/agent/SegmentTest.java | 195 +++++++++++++----- .../com/newrelic/api/agent/NoOpAgent.java | 16 ++ .../java/com/newrelic/api/agent/Segment.java | 31 +++ 5 files changed, 243 insertions(+), 55 deletions(-) diff --git a/agent-bridge/src/main/java/com/newrelic/agent/bridge/NoOpSegment.java b/agent-bridge/src/main/java/com/newrelic/agent/bridge/NoOpSegment.java index 7461875eee..9d440f33e0 100644 --- a/agent-bridge/src/main/java/com/newrelic/agent/bridge/NoOpSegment.java +++ b/agent-bridge/src/main/java/com/newrelic/agent/bridge/NoOpSegment.java @@ -10,6 +10,8 @@ import com.newrelic.api.agent.ExternalParameters; import com.newrelic.api.agent.OutboundHeaders; +import java.util.Map; + public class NoOpSegment implements TracedActivity { public static final NoOpSegment INSTANCE = new NoOpSegment(); @@ -67,4 +69,20 @@ public void end(){ public void endAsync() { } + @Override + public void addCustomAttribute(String key, Number value) { + } + + @Override + public void addCustomAttribute(String key, String value) { + } + + @Override + public void addCustomAttribute(String key, boolean value) { + } + + @Override + public void addCustomAttributes(Map attributes) { + } + } diff --git a/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java b/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java index 4863d7e832..0126b2fdf2 100644 --- a/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java +++ b/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java @@ -7,16 +7,15 @@ package com.newrelic.agent; -import com.newrelic.agent.bridge.NoOpDistributedTracePayload; import com.newrelic.agent.bridge.NoOpTracedMethod; import com.newrelic.agent.bridge.TracedMethod; import com.newrelic.agent.service.ServiceFactory; import com.newrelic.agent.tracers.Tracer; -import com.newrelic.api.agent.DistributedTracePayload; import com.newrelic.api.agent.ExternalParameters; import com.newrelic.api.agent.OutboundHeaders; import com.newrelic.api.agent.Transaction; +import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; public class Segment implements com.newrelic.agent.bridge.TracedActivity { @@ -149,6 +148,34 @@ public void endAsync() { finish(null, true); } + @Override + public void addCustomAttribute(String key, Number value) { + if (underlyingTracer != null) { + underlyingTracer.addCustomAttribute(key, value); + } + } + + @Override + public void addCustomAttribute(String key, String value) { + if (underlyingTracer != null) { + underlyingTracer.addCustomAttribute(key, value); + } + } + + @Override + public void addCustomAttribute(String key, boolean value) { + if (underlyingTracer != null) { + underlyingTracer.addCustomAttribute(key, value); + } + } + + @Override + public void addCustomAttributes(Map attributes) { + if (underlyingTracer != null) { + underlyingTracer.addCustomAttributes(attributes); + } + } + /** * {@inheritDoc} */ @@ -169,7 +196,9 @@ private void finish(final Throwable t, boolean async) { Runnable expireSegmentRunnable = new Runnable() { @Override public void run() { - tracer.getTransactionActivity().getTransaction().finishSegment(segment, t, parent, endThreadName); + tracer.getTransactionActivity() + .getTransaction() + .finishSegment(segment, t, parent, endThreadName); // Remove references to underlying and parent tracer to prevent GC issues underlyingTracer = null; @@ -195,7 +224,8 @@ public String getInitiatingThread() { public void setTruncated() { Tracer tracer = underlyingTracer; if (tracer != null) { - tracer.setMetricNameFormatInfo(tracer.getMetricName(), "Truncated/" + tracer.getMetricName(), tracer.getTransactionSegmentUri()); + tracer.setMetricNameFormatInfo(tracer.getMetricName(), "Truncated/" + tracer.getMetricName(), + tracer.getTransactionSegmentUri()); } } diff --git a/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java b/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java index 8191db35fb..2a3e952545 100644 --- a/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java +++ b/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java @@ -72,6 +72,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class SegmentTest implements ExtendedTransactionListener { @@ -187,7 +188,10 @@ public void testEndSameThread() throws InterruptedException { Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); Thread.sleep(1); - Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Sync Segment"); + Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Sync Segment"); + segment.addCustomAttribute("redbeans", "rice"); Assert.assertNotNull(segment); Thread.sleep(1); @@ -199,7 +203,8 @@ public void testEndSameThread() throws InterruptedException { root.finish(Opcodes.ARETURN, null); assertTrue(root.getTransactionActivity().getTransaction().isFinished()); - assertEquals(2, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(2, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(2, getNumTracers(root.getTransactionActivity().getTransaction())); } @@ -216,7 +221,9 @@ public void testAsync() throws InterruptedException { Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); Thread.sleep(1); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Async Segment"); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Async Segment"); Assert.assertNotNull(segment); Thread t = new Thread() { @Override @@ -243,7 +250,8 @@ public void run() { // assert num children == 2 assertTrue(root.getTransactionActivity().getTransaction().isFinished()); - assertEquals(2, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(2, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(2, getNumTracers(root.getTransactionActivity().getTransaction())); } @@ -336,13 +344,17 @@ public void testAsyncSegmentWithTimeout() throws InterruptedException { */ @Test public void testAsyncWithoutTimeout() throws InterruptedException { - final long configTimeoutMillis = ServiceFactory.getConfigService().getDefaultAgentConfig().getValue("traced_activity_timeout", 10 * 60) * 1000; + final long configTimeoutMillis = + ServiceFactory.getConfigService().getDefaultAgentConfig().getValue("traced_activity_timeout", 10 * 60) * + 1000; final Tracer root = makeTransaction(); Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); Thread.sleep(1); final long startTs = System.currentTimeMillis(); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Async Without Timeout"); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Async Without Timeout"); Assert.assertNotNull(segment); ServiceFactory.getTransactionService().processQueue(); @@ -353,10 +365,12 @@ public void testAsyncWithoutTimeout() throws InterruptedException { // this will almost always be true since the configTimeout is 3 seconds. if (durationMs < configTimeoutMillis) { // the TA was running less than the timeout when the harvest completed. Should not have been timed out. - assertEquals(2, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(2, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); } else { // the TA was running more than the timeout when the harvest completed. Could have been timed out correctly. - System.err.println("Skipping timeout assert. duration " + durationMs + " exceeds timeout " + configTimeoutMillis); + System.err.println( + "Skipping timeout assert. duration " + durationMs + " exceeds timeout " + configTimeoutMillis); } Assert.assertSame("Segment must be child of root tracer", root, segment.getTracedMethod().getParentTracedMethod()); @@ -409,7 +423,8 @@ public void run() { assertEquals("Segment name not set properly", "Custom/Unnamed Segment", ((Tracer) tracedMethod.get()).getMetricName()); - assertEquals(2, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(2, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(2, getNumTracers(root.getTransactionActivity().getTransaction())); Assert.assertSame("Segment must be child of root tracer", root, tracedMethod.get().getParentTracedMethod()); @@ -431,7 +446,9 @@ public void testPsuedoAsync1() throws InterruptedException { Assert.assertNotNull(root.getTransactionActivity().getTransaction()); Thread.sleep(1); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Psuedo Async 1"); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Psuedo Async 1"); Assert.assertNotNull(segment); root.finish(Opcodes.ARETURN, null); Thread.sleep(1); @@ -443,7 +460,8 @@ public void testPsuedoAsync1() throws InterruptedException { segment.end(); assertTrue(root.getTransactionActivity().getTransaction().isFinished()); - assertEquals(2, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(2, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(2, getNumTracers(root.getTransactionActivity().getTransaction())); } @@ -462,7 +480,9 @@ public void testSyncNamedTracedActivity() throws InterruptedException { Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); Thread.sleep(1); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Segment"); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Segment"); Assert.assertNotNull(segment); root.finish(Opcodes.ARETURN, null); Thread.sleep(1); @@ -475,7 +495,8 @@ public void testSyncNamedTracedActivity() throws InterruptedException { assertEquals("Segment name was not properly set", "activity", ((Tracer) tracedMethod.get()).getTransactionActivity().getAsyncContext()); - assertEquals(2, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(2, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(2, getNumTracers(root.getTransactionActivity().getTransaction())); Assert.assertSame("Segment must be child of root tracer", root, tracedMethod.get().getParentTracedMethod()); @@ -498,7 +519,9 @@ public void testPsuedoAsync2() throws InterruptedException { Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); Thread.sleep(1); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Psuedo Async2"); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Psuedo Async2"); Assert.assertNotNull(segment); ExitTracer child = AgentBridge.instrumentation.createTracer(null, 0, "iamyourchild", DefaultTracer.DEFAULT_TRACER_FLAGS); @@ -514,7 +537,8 @@ public void testPsuedoAsync2() throws InterruptedException { root.finish(Opcodes.ARETURN, null); assertTrue(root.getTransactionActivity().getTransaction().isFinished()); - assertEquals(2, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(2, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(3, getNumTracers(root.getTransactionActivity().getTransaction())); } @@ -527,10 +551,14 @@ public void testTracedActivityHoldsTransactionOpen() throws InterruptedException Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); Thread.sleep(1); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, Segment.UNNAMED_SEGMENT); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, Segment.UNNAMED_SEGMENT); Assert.assertNotNull(segment); Thread.sleep(1); - final Segment segment2 = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, Segment.UNNAMED_SEGMENT); + final Segment segment2 = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, Segment.UNNAMED_SEGMENT); root.finish(Opcodes.ARETURN, null); Thread.sleep(1); assertFalse(root.getTransactionActivity().getTransaction().isFinished()); @@ -549,7 +577,8 @@ public void testTracedActivityHoldsTransactionOpen() throws InterruptedException Thread.sleep(1); assertTrue(root.getTransactionActivity().getTransaction().isFinished()); - assertEquals(3, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(3, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(3, getNumTracers(root.getTransactionActivity().getTransaction())); } @@ -563,7 +592,9 @@ public void testCorrectParenting() throws InterruptedException { Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); { - final Segment segmentUnderRoot = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Under Root"); + final Segment segmentUnderRoot = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Under Root"); Assert.assertNotNull(segmentUnderRoot); Assert.assertSame("Segment has the wrong parent", root, segmentUnderRoot.getTracedMethod().getParentTracedMethod()); @@ -573,7 +604,9 @@ public void testCorrectParenting() throws InterruptedException { ExitTracer child1 = AgentBridge.instrumentation.createTracer(null, 0, "iamyourchild1", DefaultTracer.DEFAULT_TRACER_FLAGS); { - final Segment underChild1 = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Under Child"); + final Segment underChild1 = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Under Child"); Assert.assertNotNull(underChild1); Assert.assertSame("Segment has the wrong parent", child1, underChild1.getTracedMethod().getParentTracedMethod()); @@ -583,7 +616,9 @@ public void testCorrectParenting() throws InterruptedException { ExitTracer child2 = AgentBridge.instrumentation.createTracer(null, 0, "iamyourchild2", DefaultTracer.DEFAULT_TRACER_FLAGS); { - final Segment underChild2 = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Under Child 2"); + final Segment underChild2 = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Under Child 2"); Assert.assertNotNull(underChild2); Assert.assertSame("Segment has the wrong parent", child2, underChild2.getTracedMethod().getParentTracedMethod()); @@ -598,7 +633,8 @@ public void testCorrectParenting() throws InterruptedException { assertTrue(root.getTransactionActivity().getTransaction().isFinished()); // 4 txas: 1 for each of the 3 segments + 1 tracer - assertEquals(4, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(4, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(6, getNumTracers(root.getTransactionActivity().getTransaction())); } @@ -607,19 +643,27 @@ public void testMetricMigration() throws InterruptedException { Tracer root = makeTransaction(); Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Segment"); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Segment"); segment.getTracedMethod().addRollupMetricName("rollupMetric"); segment.getTracedMethod().addExclusiveRollupMetricName("exclusiveRollupMetric"); segment.end(); root.finish(Opcodes.ARETURN, null); assertTrue(root.getTransactionActivity().getTransaction().isFinished()); - ResponseTimeStats rollupMetric = root.getTransactionActivity().getTransactionStats().getUnscopedStats().getOrCreateResponseTimeStats( - "rollupMetric"); + ResponseTimeStats rollupMetric = root.getTransactionActivity() + .getTransactionStats() + .getUnscopedStats() + .getOrCreateResponseTimeStats( + "rollupMetric"); assertTrue(rollupMetric.getCallCount() == 1); - ResponseTimeStats exclusiveRollupMetric = root.getTransactionActivity().getTransactionStats().getUnscopedStats().getOrCreateResponseTimeStats( - "exclusiveRollupMetric"); + ResponseTimeStats exclusiveRollupMetric = root.getTransactionActivity() + .getTransactionStats() + .getUnscopedStats() + .getOrCreateResponseTimeStats( + "exclusiveRollupMetric"); assertTrue(exclusiveRollupMetric.getCallCount() == 1); } @@ -628,7 +672,9 @@ public void testMetricMigrationAsync() throws InterruptedException { Tracer root = makeTransaction(); Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Segment"); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Segment"); segment.getTracedMethod().addRollupMetricName("rollupMetric"); Thread finishThread = new Thread(new Runnable() { @@ -647,12 +693,18 @@ public void run() { root.finish(Opcodes.ARETURN, null); assertTrue(root.getTransactionActivity().getTransaction().isFinished()); - ResponseTimeStats rollupMetric = root.getTransactionActivity().getTransactionStats().getUnscopedStats().getOrCreateResponseTimeStats( - "rollupMetric"); + ResponseTimeStats rollupMetric = root.getTransactionActivity() + .getTransactionStats() + .getUnscopedStats() + .getOrCreateResponseTimeStats( + "rollupMetric"); assertEquals(1, rollupMetric.getCallCount()); - ResponseTimeStats exclusiveRollupMetric = root.getTransactionActivity().getTransactionStats().getUnscopedStats().getOrCreateResponseTimeStats( - "rollupMetric2"); + ResponseTimeStats exclusiveRollupMetric = root.getTransactionActivity() + .getTransactionStats() + .getUnscopedStats() + .getOrCreateResponseTimeStats( + "rollupMetric2"); assertEquals(1, exclusiveRollupMetric.getCallCount()); } @@ -662,7 +714,9 @@ public void testExclusiveTime() throws InterruptedException { Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); - final com.newrelic.agent.bridge.TracedActivity tracedActivity = AgentBridge.getAgent().getTransaction().createAndStartTracedActivity(); + final com.newrelic.agent.bridge.TracedActivity tracedActivity = AgentBridge.getAgent() + .getTransaction() + .createAndStartTracedActivity(); DefaultTracer underlyingTracer = (DefaultTracer) tracedActivity.getTracedMethod(); Thread.sleep(10); tracedActivity.end(); @@ -682,7 +736,9 @@ public void testExclusiveTimeAsync() throws InterruptedException { Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Segment"); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Segment"); Thread finishThread = new Thread(new Runnable() { @Override public void run() { @@ -716,14 +772,17 @@ public void testIgnoreTransaction() throws InterruptedException { root.getTransactionActivity().getTransaction().ignore(); Thread.sleep(1); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Segment"); - Assert.assertNull(segment); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Segment"); + assertNull(segment); Thread.sleep(1); root.finish(Opcodes.ARETURN, null); assertTrue(root.getTransactionActivity().getTransaction().isFinished()); //I think reporting a 0 instead of a 1 is fine here - assertEquals(0, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(0, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(1, getNumTracers(root.getTransactionActivity().getTransaction())); } @@ -736,14 +795,17 @@ public void testIgnore() throws InterruptedException { Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); Thread.sleep(1); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Segment"); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Segment"); Assert.assertNotNull(segment); Thread.sleep(1); segment.ignoreIfUnfinished(); root.finish(Opcodes.ARETURN, null); assertTrue(root.getTransactionActivity().getTransaction().isFinished()); - assertEquals(1, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(1, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(1, getNumTracers(root.getTransactionActivity().getTransaction())); } @@ -757,7 +819,9 @@ public void testIgnoreAsync() throws InterruptedException { Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); Thread.sleep(1); - final Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Segment"); + final Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Segment"); root.finish(Opcodes.ARETURN, null); Thread t = new Thread() { @Override @@ -776,7 +840,8 @@ public void run() { t.join(); assertTrue(root.getTransactionActivity().getTransaction().isFinished()); - assertEquals(1, root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); + assertEquals(1, + root.getTransactionActivity().getTransaction().getCountOfRunningAndFinishedTransactionActivities()); assertEquals(1, getNumTracers(root.getTransactionActivity().getTransaction())); } @@ -786,7 +851,9 @@ public void testAsyncContextAttributeEndSameThread() { Assert.assertNotNull(root); Assert.assertNotNull(root.getTransactionActivity().getTransaction()); - Segment segment = root.getTransactionActivity().getTransaction().startSegment(MetricNames.CUSTOM, "Custom Segment"); + Segment segment = root.getTransactionActivity() + .getTransaction() + .startSegment(MetricNames.CUSTOM, "Custom Segment"); Assert.assertNotNull(segment); segment.end(); @@ -799,7 +866,7 @@ public void testAsyncContextAttributeEndSameThread() { assertEquals(0, tracers.size()); TransactionActivity segmentTxa = findSegmentTxa(root.getTransactionActivity().getTransaction()); - Assert.assertNull(segmentTxa.getRootTracer().getAgentAttribute("async_context")); + assertNull(segmentTxa.getRootTracer().getAgentAttribute("async_context")); } @Test @@ -851,7 +918,8 @@ private static Map createConfigMap() { return map; } - private static void createServiceManager(Map map, ExpirationService expirationService) throws Exception { + private static void createServiceManager(Map map, ExpirationService expirationService) + throws Exception { ConfigService configService = ConfigServiceFactory.createConfigServiceUsingSettings(map); MockServiceManager serviceManager = new MockServiceManager(configService); ServiceFactory.setServiceManager(serviceManager); @@ -894,8 +962,10 @@ private static void createServiceManager(Map map, ExpirationServ distributedTraceService.connected(null, AgentConfigFactory.createAgentConfig(configMap, null, null)); serviceManager.setDistributedTraceService(distributedTraceService); - TransactionDataToDistributedTraceIntrinsics transactionDataToDistributedTraceIntrinsics = new TransactionDataToDistributedTraceIntrinsics(distributedTraceService); - serviceManager.setTransactionEventsService(new TransactionEventsService(transactionDataToDistributedTraceIntrinsics)); + TransactionDataToDistributedTraceIntrinsics transactionDataToDistributedTraceIntrinsics = new TransactionDataToDistributedTraceIntrinsics( + distributedTraceService); + serviceManager.setTransactionEventsService( + new TransactionEventsService(transactionDataToDistributedTraceIntrinsics)); MockRPMServiceManager rpmServiceManager = new MockRPMServiceManager(); serviceManager.setRPMServiceManager(rpmServiceManager); @@ -963,11 +1033,11 @@ public void confirmTxnGc() { // Please, please, run the gc System.gc(); - Assert.assertNull(seg.getParent()); + assertNull(seg.getParent()); // Need to find if the underlying txn is still alive. com.newrelic.api.agent.Transaction tx = seg.getTransaction(); - Assert.assertNull("Transaction was not garbage collected", tx); + assertNull("Transaction was not garbage collected", tx); } @Test @@ -1031,9 +1101,9 @@ public void testSameThreadSegmentTracerAttributes() throws InterruptedException root.finish(Opcodes.ARETURN, null); assertTrue(root.getTransactionActivity().getTransaction().isFinished()); - Assert.assertNull(segmentTracer.getAgentAttribute(Segment.START_THREAD)); - Assert.assertNull(segmentTracer.getAgentAttribute(Segment.END_THREAD)); - Assert.assertNull(segmentTracer.getAgentAttribute("async_context")); + assertNull(segmentTracer.getAgentAttribute(Segment.START_THREAD)); + assertNull(segmentTracer.getAgentAttribute(Segment.END_THREAD)); + assertNull(segmentTracer.getAgentAttribute("async_context")); } @Test(timeout = 30000) @@ -1140,6 +1210,29 @@ public void setHeader(String name, String value) { assertEquals(segmentSpanEvent.getGuid(), secondRootTracerSpanEvent.getParentId()); } + @Test + public void testAddCustomAttributeNoCheckLimit() { + Transaction.clearTransaction(); + Tracer rootTracer = makeTransaction(); + Transaction tx = rootTracer.getTransactionActivity().getTransaction(); + Segment segment = tx.startSegment("custom", "segment"); + + segment.addCustomAttribute("redbeans", "rice"); + segment.addCustomAttribute("numBeans", 400); + segment.addCustomAttribute("sausage", true); + segment.addCustomAttribute(null, "Keys cant be null"); + Map extras = new HashMap<>(); + extras.put("pickles", null); + extras.put("hotSauce", true); + segment.addCustomAttributes(extras); + + assertEquals(4, segment.getTracer().getCustomAttributes().size()); + assertEquals("rice", segment.getTracer().getCustomAttributes().get("redbeans")); + assertEquals(400, segment.getTracer().getCustomAttributes().get("numBeans")); + assertTrue((Boolean) segment.getTracer().getCustomAttributes().get("sausage")); + assertTrue((Boolean) segment.getTracer().getCustomAttributes().get("hotSauce")); + } + private SpanEvent findSpanByName(List spanEvents, String spanName) { for (SpanEvent spanEvent : spanEvents) { if (spanEvent.getName().equals(spanName)) { diff --git a/newrelic-api/src/main/java/com/newrelic/api/agent/NoOpAgent.java b/newrelic-api/src/main/java/com/newrelic/api/agent/NoOpAgent.java index 65499cbd50..4da1d34fe7 100644 --- a/newrelic-api/src/main/java/com/newrelic/api/agent/NoOpAgent.java +++ b/newrelic-api/src/main/java/com/newrelic/api/agent/NoOpAgent.java @@ -366,6 +366,22 @@ public void end() { @Override public void endAsync() { } + + @Override + public void addCustomAttribute(String key, Number value) { + } + + @Override + public void addCustomAttribute(String key, String value) { + } + + @Override + public void addCustomAttribute(String key, boolean value) { + } + + @Override + public void addCustomAttributes(Map attributes) { + } }; private static final TraceMetadata TRACE_METADATA = new TraceMetadata() { diff --git a/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java b/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java index 17dcffdc52..344831756f 100644 --- a/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java +++ b/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java @@ -7,6 +7,8 @@ package com.newrelic.api.agent; +import java.util.Map; + /** *

* Represents a timed unit of work. Like a {@link TracedMethod}, reports a single metric, @@ -92,4 +94,33 @@ public interface Segment { * @since 5.4.0 */ void endAsync(); + + /** + * Adds/Replaces a numerical attribute on the current segment. + * + * @since 6.1.0 + */ + void addCustomAttribute(String key, Number value); // + // + /** + * Adds/Replaces a string attribute on the current segment. + * + * @since 6.1.0 + */ + void addCustomAttribute(String key, String value); + + /** + * Adds/Replaces a boolean attribute on the current segment. + * + * @since 6.1.0 + */ + void addCustomAttribute(String key, boolean value); + + /** + * Adds/Replaces key/value pairs on the current segment. + * + * @since 6.1.0 + */ + void addCustomAttributes(Map attributes); + } From 2994458f84acb681da20f7a8d5732a30a4564fa5 Mon Sep 17 00:00:00 2001 From: Thomas Spring Date: Thu, 17 Sep 2020 10:29:58 -0700 Subject: [PATCH 2/4] Refactor common interface --- .../main/java/com/newrelic/agent/Segment.java | 3 +- .../agent/tracers/AbstractTracer.java | 3 +- .../newrelic/api/agent/AttributeCarrying.java | 36 +++++++++++++++++++ .../java/com/newrelic/api/agent/Segment.java | 30 +--------------- .../com/newrelic/api/agent/TracedMethod.java | 30 +--------------- 5 files changed, 42 insertions(+), 60 deletions(-) create mode 100644 newrelic-api/src/main/java/com/newrelic/api/agent/AttributeCarrying.java diff --git a/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java b/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java index 0126b2fdf2..6bc8f840de 100644 --- a/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java +++ b/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java @@ -11,6 +11,7 @@ import com.newrelic.agent.bridge.TracedMethod; import com.newrelic.agent.service.ServiceFactory; import com.newrelic.agent.tracers.Tracer; +import com.newrelic.api.agent.AttributeCarrying; import com.newrelic.api.agent.ExternalParameters; import com.newrelic.api.agent.OutboundHeaders; import com.newrelic.api.agent.Transaction; @@ -18,7 +19,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; -public class Segment implements com.newrelic.agent.bridge.TracedActivity { +public class Segment implements com.newrelic.agent.bridge.TracedActivity, AttributeCarrying { private volatile Tracer underlyingTracer; private volatile Tracer parent; private volatile WeakRefTransaction weakRefTransaction; diff --git a/newrelic-agent/src/main/java/com/newrelic/agent/tracers/AbstractTracer.java b/newrelic-agent/src/main/java/com/newrelic/agent/tracers/AbstractTracer.java index 7cee91ab42..843b50e112 100644 --- a/newrelic-agent/src/main/java/com/newrelic/agent/tracers/AbstractTracer.java +++ b/newrelic-agent/src/main/java/com/newrelic/agent/tracers/AbstractTracer.java @@ -8,6 +8,7 @@ package com.newrelic.agent.tracers; import com.newrelic.agent.Agent; +import com.newrelic.api.agent.AttributeCarrying; import com.newrelic.agent.MetricNames; import com.newrelic.agent.Transaction; import com.newrelic.agent.TransactionActivity; @@ -36,7 +37,7 @@ /** * Base class for all tracers. This implements {@link InvocationHandler#invoke(Object, Method, Object[])} */ -public abstract class AbstractTracer implements Tracer { +public abstract class AbstractTracer implements Tracer, AttributeCarrying { static final int INITIAL_PARAMETER_MAP_SIZE = 5; protected static String ATTRIBUTE_TYPE = "custom"; diff --git a/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeCarrying.java b/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeCarrying.java new file mode 100644 index 0000000000..61b73ae204 --- /dev/null +++ b/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeCarrying.java @@ -0,0 +1,36 @@ +package com.newrelic.api.agent; + +import java.util.Map; + + +public interface AttributeCarrying { + + /** + * Adds/Replaces a numerical attribute on the current tracer. + * + * @since 6.1.0 + */ + void addCustomAttribute(String key, Number value); // + + /** + * Adds/Replaces a string attribute on the current tracer. + * + * @since 6.1.0 + */ + void addCustomAttribute(String key, String value); + + /** + * Adds/Replaces a boolean attribute on the current tracer. + * + * @since 6.1.0 + */ + void addCustomAttribute(String key, boolean value); + + /** + * Adds/Replaces key/value pairs on the current tracer. + * + * @since 6.1.0 + */ + void addCustomAttributes(Map attributes); + +} diff --git a/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java b/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java index 344831756f..9b9b279c5a 100644 --- a/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java +++ b/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java @@ -7,7 +7,6 @@ package com.newrelic.api.agent; -import java.util.Map; /** *

@@ -25,7 +24,7 @@ * A {@link Segment} will show up in the Transaction Breakdown table, as well as the Transaction Trace page in APM. *

*/ -public interface Segment { +public interface Segment extends AttributeCarrying { /** * Sets the metric name by concatenating all given metricNameParts with a '/' separating each part. @@ -95,32 +94,5 @@ public interface Segment { */ void endAsync(); - /** - * Adds/Replaces a numerical attribute on the current segment. - * - * @since 6.1.0 - */ - void addCustomAttribute(String key, Number value); // - // - /** - * Adds/Replaces a string attribute on the current segment. - * - * @since 6.1.0 - */ - void addCustomAttribute(String key, String value); - - /** - * Adds/Replaces a boolean attribute on the current segment. - * - * @since 6.1.0 - */ - void addCustomAttribute(String key, boolean value); - - /** - * Adds/Replaces key/value pairs on the current segment. - * - * @since 6.1.0 - */ - void addCustomAttributes(Map attributes); } diff --git a/newrelic-api/src/main/java/com/newrelic/api/agent/TracedMethod.java b/newrelic-api/src/main/java/com/newrelic/api/agent/TracedMethod.java index 22f8a7ebd0..1de88e9aee 100644 --- a/newrelic-api/src/main/java/com/newrelic/api/agent/TracedMethod.java +++ b/newrelic-api/src/main/java/com/newrelic/api/agent/TracedMethod.java @@ -15,35 +15,7 @@ * * @see Agent#getTracedMethod() */ -public interface TracedMethod { - - /** - * Adds/Replaces a numerical attribute on the current traced method. - * - * @since 5.13.0 - */ - void addCustomAttribute(String key, Number value); - - /** - * Adds/Replaces a string attribute on the current traced method. - * - * @since 5.13.0 - */ - void addCustomAttribute(String key, String value); - - /** - * Adds/Replaces a boolean attribute on the current traced method. - * - * @since 5.13.0 - */ - void addCustomAttribute(String key, boolean value); - - /** - * Adds/Replaces key/value pairs on the current traced method. - * - * @since 5.13.0 - */ - void addCustomAttributes(Map attributes); +public interface TracedMethod extends AttributeCarrying { /** * Returns the traced method metric name. From 13cb0d9e69bce566cfd7b3c624ca7305b0a17e1f Mon Sep 17 00:00:00 2001 From: Thomas Spring Date: Sat, 19 Sep 2020 19:37:00 -0700 Subject: [PATCH 3/4] #47 Add custom attributes to async segment tracers --- .../main/java/com/newrelic/agent/Segment.java | 4 +- .../agent/attributes/AttributeValidator.java | 14 +++++-- .../agent/tracers/AbstractTracer.java | 6 +-- .../java/com/newrelic/agent/SegmentTest.java | 38 ++++++++++++++++++- ...buteCarrying.java => AttributeHolder.java} | 4 +- .../java/com/newrelic/api/agent/Segment.java | 2 +- .../com/newrelic/api/agent/TracedMethod.java | 4 +- 7 files changed, 56 insertions(+), 16 deletions(-) rename newrelic-api/src/main/java/com/newrelic/api/agent/{AttributeCarrying.java => AttributeHolder.java} (87%) diff --git a/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java b/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java index 6bc8f840de..bbb0d91392 100644 --- a/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java +++ b/newrelic-agent/src/main/java/com/newrelic/agent/Segment.java @@ -11,7 +11,7 @@ import com.newrelic.agent.bridge.TracedMethod; import com.newrelic.agent.service.ServiceFactory; import com.newrelic.agent.tracers.Tracer; -import com.newrelic.api.agent.AttributeCarrying; +import com.newrelic.api.agent.AttributeHolder; import com.newrelic.api.agent.ExternalParameters; import com.newrelic.api.agent.OutboundHeaders; import com.newrelic.api.agent.Transaction; @@ -19,7 +19,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; -public class Segment implements com.newrelic.agent.bridge.TracedActivity, AttributeCarrying { +public class Segment implements com.newrelic.agent.bridge.TracedActivity, AttributeHolder { private volatile Tracer underlyingTracer; private volatile Tracer parent; private volatile WeakRefTransaction weakRefTransaction; diff --git a/newrelic-agent/src/main/java/com/newrelic/agent/attributes/AttributeValidator.java b/newrelic-agent/src/main/java/com/newrelic/agent/attributes/AttributeValidator.java index c2ecf118a0..13d76d4518 100644 --- a/newrelic-agent/src/main/java/com/newrelic/agent/attributes/AttributeValidator.java +++ b/newrelic-agent/src/main/java/com/newrelic/agent/attributes/AttributeValidator.java @@ -16,7 +16,11 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.StandardCharsets; -import java.util.*; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -34,7 +38,8 @@ private String getAttributeType() { private boolean isTransactional = true; // Set of APIs that can report attributes outside of a transaction - private static final Collection sendParametersOutsideOfTxn = Arrays.asList("noticeError", "Span.addCustomParameter", "Span.addCustomParameters"); + private static final Collection sendParametersOutsideOfTxn = Arrays.asList("noticeError", + "Span.addCustomParameter", "Span.addCustomParameters", "TracedMethod.addCustomAttributes"); public AttributeValidator(String attributeType) { this.attributeType = attributeType; @@ -133,7 +138,8 @@ protected Map verifyParametersAndReturnValues(Map finishTime = new AtomicReference<>(null); - private final String ATTRIBUTE_API_METHOD_NAME = "TracedMethod addCustomAttributes"; + private final String ATTRIBUTE_API_METHOD_NAME = "TracedMethod.addCustomAttributes"; // Tracers MUST NOT store references to the Transaction. Why: tracers are stored in the TransactionActivity, // and Activities can be reparented from one Transaction to another by the public APIs that support async. diff --git a/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java b/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java index 2a3e952545..eda40eb070 100644 --- a/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java +++ b/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java @@ -1211,7 +1211,7 @@ public void setHeader(String name, String value) { } @Test - public void testAddCustomAttributeNoCheckLimit() { + public void testSegmentAddCustomAttributeSync() { Transaction.clearTransaction(); Tracer rootTracer = makeTransaction(); Transaction tx = rootTracer.getTransactionActivity().getTransaction(); @@ -1233,6 +1233,42 @@ public void testAddCustomAttributeNoCheckLimit() { assertTrue((Boolean) segment.getTracer().getCustomAttributes().get("hotSauce")); } + @Test + public void testSegmentAddCustomAttributeAsync() throws InterruptedException { + Tracer root = makeTransaction(); + final Transaction txn = root.getTransactionActivity().getTransaction(); + final Segment segment = txn.startSegment("custom", "Segment Name"); + final AtomicReference segmentTracerRef = new AtomicReference<>(); + + Thread finishThread = new Thread(new Runnable() { + + @Override + public void run() { + segment.addCustomAttribute("redbeans", "rice"); + segment.addCustomAttribute("numBeans", 400); + segment.addCustomAttribute("sausage", true); + segment.addCustomAttribute(null, "Keys cant be null"); + Map extras = new HashMap<>(); + extras.put("pickles", null); + extras.put("hotSauce", true); + segment.addCustomAttributes(extras); + + Thread.currentThread().setName("Second Thread"); + segmentTracerRef.set(segment.getTracer()); + segment.end(); + } + }); + + finishThread.start(); + finishThread.join(); + Tracer tracer = segmentTracerRef.get(); + assertEquals(4, tracer.getCustomAttributes().size()); + assertEquals("rice", tracer.getCustomAttributes().get("redbeans")); + assertEquals(400, tracer.getCustomAttributes().get("numBeans")); + assertTrue((Boolean) tracer.getCustomAttributes().get("sausage")); + assertTrue((Boolean) tracer.getCustomAttributes().get("hotSauce")); + } + private SpanEvent findSpanByName(List spanEvents, String spanName) { for (SpanEvent spanEvent : spanEvents) { if (spanEvent.getName().equals(spanName)) { diff --git a/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeCarrying.java b/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeHolder.java similarity index 87% rename from newrelic-api/src/main/java/com/newrelic/api/agent/AttributeCarrying.java rename to newrelic-api/src/main/java/com/newrelic/api/agent/AttributeHolder.java index 61b73ae204..810def1037 100644 --- a/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeCarrying.java +++ b/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeHolder.java @@ -3,14 +3,14 @@ import java.util.Map; -public interface AttributeCarrying { +public interface AttributeHolder { /** * Adds/Replaces a numerical attribute on the current tracer. * * @since 6.1.0 */ - void addCustomAttribute(String key, Number value); // + void addCustomAttribute(String key, Number value); /** * Adds/Replaces a string attribute on the current tracer. diff --git a/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java b/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java index 9b9b279c5a..3dd9a1e342 100644 --- a/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java +++ b/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java @@ -24,7 +24,7 @@ * A {@link Segment} will show up in the Transaction Breakdown table, as well as the Transaction Trace page in APM. *

*/ -public interface Segment extends AttributeCarrying { +public interface Segment extends AttributeHolder { /** * Sets the metric name by concatenating all given metricNameParts with a '/' separating each part. diff --git a/newrelic-api/src/main/java/com/newrelic/api/agent/TracedMethod.java b/newrelic-api/src/main/java/com/newrelic/api/agent/TracedMethod.java index 1de88e9aee..5c825df608 100644 --- a/newrelic-api/src/main/java/com/newrelic/api/agent/TracedMethod.java +++ b/newrelic-api/src/main/java/com/newrelic/api/agent/TracedMethod.java @@ -7,15 +7,13 @@ package com.newrelic.api.agent; -import java.util.Map; - /** * Represents a single instance of the timing mechanism associated with a method that is instrumented using the * {@link Trace} annotation. * * @see Agent#getTracedMethod() */ -public interface TracedMethod extends AttributeCarrying { +public interface TracedMethod extends AttributeHolder { /** * Returns the traced method metric name. From 702e813f4c21b285cb5e83301e8ddf8be0470c23 Mon Sep 17 00:00:00 2001 From: Thomas Spring Date: Mon, 21 Sep 2020 15:57:20 -0700 Subject: [PATCH 4/4] Clean up tests and javadocs --- .../test/java/com/newrelic/agent/SegmentTest.java | 13 +++++++------ .../com/newrelic/api/agent/AttributeHolder.java | 8 ++++---- .../main/java/com/newrelic/api/agent/Segment.java | 3 --- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java b/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java index eda40eb070..a7dff36e5e 100644 --- a/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java +++ b/newrelic-agent/src/test/java/com/newrelic/agent/SegmentTest.java @@ -191,7 +191,6 @@ public void testEndSameThread() throws InterruptedException { Segment segment = root.getTransactionActivity() .getTransaction() .startSegment(MetricNames.CUSTOM, "Custom Sync Segment"); - segment.addCustomAttribute("redbeans", "rice"); Assert.assertNotNull(segment); Thread.sleep(1); @@ -1216,6 +1215,7 @@ public void testSegmentAddCustomAttributeSync() { Tracer rootTracer = makeTransaction(); Transaction tx = rootTracer.getTransactionActivity().getTransaction(); Segment segment = tx.startSegment("custom", "segment"); + Tracer tracer = segment.getTracer(); segment.addCustomAttribute("redbeans", "rice"); segment.addCustomAttribute("numBeans", 400); @@ -1225,12 +1225,13 @@ public void testSegmentAddCustomAttributeSync() { extras.put("pickles", null); extras.put("hotSauce", true); segment.addCustomAttributes(extras); + segment.end(); - assertEquals(4, segment.getTracer().getCustomAttributes().size()); - assertEquals("rice", segment.getTracer().getCustomAttributes().get("redbeans")); - assertEquals(400, segment.getTracer().getCustomAttributes().get("numBeans")); - assertTrue((Boolean) segment.getTracer().getCustomAttributes().get("sausage")); - assertTrue((Boolean) segment.getTracer().getCustomAttributes().get("hotSauce")); + assertEquals(4, tracer.getCustomAttributes().size()); + assertEquals("rice", tracer.getCustomAttributes().get("redbeans")); + assertEquals(400, tracer.getCustomAttributes().get("numBeans")); + assertTrue((Boolean) tracer.getCustomAttributes().get("sausage")); + assertTrue((Boolean) tracer.getCustomAttributes().get("hotSauce")); } @Test diff --git a/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeHolder.java b/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeHolder.java index 810def1037..d4c0f36006 100644 --- a/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeHolder.java +++ b/newrelic-api/src/main/java/com/newrelic/api/agent/AttributeHolder.java @@ -6,28 +6,28 @@ public interface AttributeHolder { /** - * Adds/Replaces a numerical attribute on the current tracer. + * Adds/Replaces a numerical attribute. * * @since 6.1.0 */ void addCustomAttribute(String key, Number value); /** - * Adds/Replaces a string attribute on the current tracer. + * Adds/Replaces a string attribute. * * @since 6.1.0 */ void addCustomAttribute(String key, String value); /** - * Adds/Replaces a boolean attribute on the current tracer. + * Adds/Replaces a boolean attribute. * * @since 6.1.0 */ void addCustomAttribute(String key, boolean value); /** - * Adds/Replaces key/value pairs on the current tracer. + * Adds/Replaces key/value pairs. * * @since 6.1.0 */ diff --git a/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java b/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java index 3dd9a1e342..d5f9108fc1 100644 --- a/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java +++ b/newrelic-api/src/main/java/com/newrelic/api/agent/Segment.java @@ -7,7 +7,6 @@ package com.newrelic.api.agent; - /** *

* Represents a timed unit of work. Like a {@link TracedMethod}, reports a single metric, @@ -93,6 +92,4 @@ public interface Segment extends AttributeHolder { * @since 5.4.0 */ void endAsync(); - - }