Skip to content

Commit

Permalink
Merge branch 'saxon-db-attr-pr-dup' of github.com:newrelic/newrelic-j…
Browse files Browse the repository at this point in the history
…ava-agent into saxon-db-attr-pr-dup
  • Loading branch information
obenkenobi committed Oct 6, 2023
2 parents 2912d54 + 245e9a7 commit a53fcfc
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 9 deletions.
17 changes: 13 additions & 4 deletions agent-model/src/main/java/com/newrelic/agent/model/SpanEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,14 @@
import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public class SpanEvent extends AnalyticsEvent implements JSONStreamAware {

public static final String SPAN = "Span";
static final String SPAN_KIND = "client";
static final String CLIENT_SPAN_KIND = "client";

private final String appName;
private final Map<String, Object> intrinsics;
Expand Down Expand Up @@ -120,6 +118,7 @@ public static class Builder {
private float priority;
private boolean decider;
private long timestamp;
private Object spanKind;

public Builder appName(String appName) {
this.appName = appName;
Expand Down Expand Up @@ -177,9 +176,19 @@ public Builder putAgentAttribute(String key, Object value) {
return this;
}

public Builder spanKind(Object spanKind) {
putIntrinsic("span.kind", spanKind);
this.spanKind = spanKind;
return this;
}

public boolean isClientSpan() {
return CLIENT_SPAN_KIND.equals(spanKind);
}

public Object getSpanKindFromUserAttributes() {
Object result = userAttributes.get("span.kind");
return result == null ? SPAN_KIND : result;
return result == null ? CLIENT_SPAN_KIND : result;
}

public Builder decider(boolean decider) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public final class AttributeNames {
public static final String TIMEOUT_CAUSE = "nr.timeoutCause";
public static final String ERROR_EXPECTED = "error.expected";

public static final String CODE_STACKTRACE = "code.stacktrace";
public static final String COMPONENT = "component";
public static final String HTTP_METHOD = "http.method";
public static final String HTTP_STATUS_CODE = "http.statusCode";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@
import com.newrelic.agent.model.SpanError;
import com.newrelic.agent.model.SpanEvent;
import com.newrelic.agent.service.ServiceFactory;
import com.newrelic.agent.tracers.DefaultTracer;
import com.newrelic.agent.util.ExternalsUtil;
import com.newrelic.agent.util.StackTraces;
import com.newrelic.api.agent.DatastoreParameters;
import com.newrelic.api.agent.ExternalParameters;
import com.newrelic.api.agent.HttpParameters;
import com.newrelic.api.agent.SlowQueryDatastoreParameters;

import java.net.URI;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
Expand All @@ -40,6 +43,7 @@ public class SpanEventFactory {
private static final Joiner TRACE_STATE_VENDOR_JOINER = Joiner.on(",");
// Truncate `db.statement` at 2000 characters
private static final int DB_STATEMENT_TRUNCATE_LENGTH = 2000;
private static final int MAX_EVENT_ATTRIBUTE_STRING_LENGTH = 4095;

public static final Supplier<Long> DEFAULT_SYSTEM_TIMESTAMP_SUPPLIER = System::currentTimeMillis;

Expand Down Expand Up @@ -115,13 +119,30 @@ public SpanEventFactory putAllAgentAttributes(Map<String, ?> agentAttributes) {
return this;
}

/**
* This should be called after the span kind is set.
*/
public SpanEventFactory setStackTraceAttributes(Map<String, Object> agentAttributes) {
if (builder.isClientSpan()) {
final List<StackTraceElement> stackTraceList = (List<StackTraceElement>) agentAttributes.get(DefaultTracer.BACKTRACE_PARAMETER_NAME);
if (stackTraceList != null) {
final List<StackTraceElement> preStackTraces = StackTraces.scrubAndTruncate(stackTraceList);
final List<String> postParentRemovalTrace = StackTraces.toStringList(preStackTraces);

putAgentAttribute(AttributeNames.CODE_STACKTRACE, truncateWithEllipsis(
Joiner.on(',').join(postParentRemovalTrace), MAX_EVENT_ATTRIBUTE_STRING_LENGTH));
}
}
return this;
}

public SpanEventFactory setClmAttributes(Map<String, Object> agentAttributes) {
if (agentAttributes == null || agentAttributes.isEmpty()) {
return this;
}
final Object threadId = agentAttributes.get(AttributeNames.THREAD_ID);
if (threadId != null) {
builder.putAgentAttribute(AttributeNames.THREAD_ID, threadId);
builder.putIntrinsic(AttributeNames.THREAD_ID, threadId);
}
if (agentAttributes.containsKey(AttributeNames.CLM_NAMESPACE) && agentAttributes.containsKey(AttributeNames.CLM_FUNCTION)) {
builder.putAgentAttribute(AttributeNames.CLM_NAMESPACE, agentAttributes.get(AttributeNames.CLM_NAMESPACE));
Expand All @@ -136,6 +157,12 @@ public SpanEventFactory putAllUserAttributes(Map<String, ?> userAttributes) {
return this;
}


public SpanEventFactory putAllUserAttributesIfAbsent(Map<String, ?> userAttributes) {
builder.putAllUserAttributesIfAbsent(filter.filterUserAttributes(appName, userAttributes));
return this;
}

public SpanEventFactory putAgentAttribute(String key, Object value) {
builder.putAgentAttribute(key, value);
return this;
Expand Down Expand Up @@ -164,8 +191,7 @@ public SpanEventFactory setCategory(SpanCategory category) {
}

public SpanEventFactory setKindFromUserAttributes() {
Object spanKind = builder.getSpanKindFromUserAttributes();
builder.putIntrinsic("span.kind", spanKind);
builder.spanKind(builder.getSpanKindFromUserAttributes());
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public SpanEvent createSpanEvent(Tracer tracer, TransactionData transactionData,
.setTimestamp(tracer.getStartTimeInMillis())
.setPriority(transactionData.getPriority())
.setExternalParameterAttributes(tracer.getExternalParameters())
.setStackTraceAttributes(tracer.getAgentAttributes())
.setIsRootSpanEvent(isRoot)
.setDecider(inboundPayload == null || inboundPayload.priority == null);

Expand Down
7 changes: 6 additions & 1 deletion newrelic-agent/src/main/resources/META-INF/excludes
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,9 @@
# exclusions for Open Liberty 21+ so transactions start properly
^com/ibm/ws/security/jaspi/JaspiServletFilter
# Websphere specific servlet wrapper class
^com/ibm/ws/webcontainer/servlet/ServletWrapperImpl
^com/ibm/ws/webcontainer/servlet/ServletWrapperImpl
# Sonarqube9.9 ClassCircularityErrors
^java/util/AbstractList\$RandomAccessSpliterator
^java/util/stream/MatchOps\$MatchOp
^java/util/stream/MatchOps\$BooleanTerminalSink
^javax/security/auth/Subject\$SecureSet\$1
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,29 @@
package com.newrelic.agent.service.analytics;

import com.google.common.collect.ImmutableMap;
import com.newrelic.agent.MockConfigService;
import com.newrelic.agent.MockServiceManager;
import com.newrelic.agent.attributes.AttributeNames;
import com.newrelic.agent.config.AgentConfig;
import com.newrelic.agent.model.AttributeFilter;
import com.newrelic.agent.model.SpanCategory;
import com.newrelic.agent.model.SpanError;
import com.newrelic.agent.model.SpanEvent;
import com.newrelic.agent.service.ServiceFactory;
import com.newrelic.agent.tracers.DefaultTracer;
import com.newrelic.api.agent.DatastoreParameters;
import com.newrelic.api.agent.HttpParameters;
import org.junit.Test;

import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;

import static com.newrelic.agent.service.analytics.SpanEventFactory.DEFAULT_SYSTEM_TIMESTAMP_SUPPLIER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -196,6 +202,21 @@ public void shouldSetDataStoreParameters() {
assertEquals("dbserver:3306", target.getAgentAttributes().get("peer.address"));
}

@Test
public void shouldStoreStackTrace() {
SpanEventFactory spanEventFactory = new SpanEventFactory("MyApp", new AttributeFilter.PassEverythingAttributeFilter(),
DEFAULT_SYSTEM_TIMESTAMP_SUPPLIER);
spanEventFactory.setKindFromUserAttributes();
MockServiceManager serviceManager = new MockServiceManager();
serviceManager.setConfigService(new MockConfigService(mock(AgentConfig.class)));
ServiceFactory.setServiceManager(serviceManager);
spanEventFactory.setStackTraceAttributes(
ImmutableMap.of(DefaultTracer.BACKTRACE_PARAMETER_NAME, Arrays.asList(Thread.currentThread().getStackTrace())));

final Object stackTrace = spanEventFactory.build().getAgentAttributes().get(AttributeNames.CODE_STACKTRACE);
assertNotNull(stackTrace);
}

@Test
public void shouldSetCLMParameters() {
Map<String, Object> agentAttributes = ImmutableMap.of(
Expand All @@ -208,7 +229,7 @@ public void shouldSetCLMParameters() {

assertEquals("nr", target.getAgentAttributes().get(AttributeNames.CLM_NAMESPACE));
assertEquals("process", target.getAgentAttributes().get(AttributeNames.CLM_FUNCTION));
assertEquals(666, target.getAgentAttributes().get(AttributeNames.THREAD_ID));
assertEquals(666, target.getIntrinsics().get(AttributeNames.THREAD_ID));
}

@Test
Expand Down

0 comments on commit a53fcfc

Please sign in to comment.