From 75bceb76ff86f65fe68db0eb17fe0ca9f8f8daba Mon Sep 17 00:00:00 2001 From: Enriqueta De Leon Date: Wed, 17 Jan 2024 14:08:25 -0800 Subject: [PATCH] Add Null Checks for Synthetics-Info Header Attributes (#1690) * added null checks for synthetics-info attrs before adding to intrinsics --- .../newrelic/agent/InboundHeaderState.java | 6 +- .../java/com/newrelic/agent/Transaction.java | 27 ++++--- .../com/newrelic/agent/TransactionTest.java | 71 ++++++++++++++++++- 3 files changed, 91 insertions(+), 13 deletions(-) diff --git a/newrelic-agent/src/main/java/com/newrelic/agent/InboundHeaderState.java b/newrelic-agent/src/main/java/com/newrelic/agent/InboundHeaderState.java index c3f582eea6..2e058dc669 100644 --- a/newrelic-agent/src/main/java/com/newrelic/agent/InboundHeaderState.java +++ b/newrelic-agent/src/main/java/com/newrelic/agent/InboundHeaderState.java @@ -57,7 +57,11 @@ public InboundHeaderState(Transaction tx, InboundHeaders inboundHeaders) { this.catState = CatState.NONE; } else { this.synState = parseSyntheticsHeader(); - this.synInfoState = parseSyntheticsInfoHeader(); + if (inboundHeaders.getHeader("X-NewRelic-Synthetics-Info") == null) { + this.synInfoState = SyntheticsInfoState.NONE; + } else { + this.synInfoState = parseSyntheticsInfoHeader(); + } if (tx.getAgentConfig().getDistributedTracingConfig().isEnabled() && tx.getSpanProxy().getInboundDistributedTracePayload() == null) { parseDistributedTraceHeaders(); this.catState = CatState.NONE; diff --git a/newrelic-agent/src/main/java/com/newrelic/agent/Transaction.java b/newrelic-agent/src/main/java/com/newrelic/agent/Transaction.java index 99b40e47fa..3829699352 100644 --- a/newrelic-agent/src/main/java/com/newrelic/agent/Transaction.java +++ b/newrelic-agent/src/main/java/com/newrelic/agent/Transaction.java @@ -1093,19 +1093,24 @@ private void finishTransaction() { this.getInboundHeaderState().getSyntheticsMonitorId()); getIntrinsicAttributes().put(AttributeNames.SYNTHETICS_JOB_ID, this.getInboundHeaderState().getSyntheticsJobId()); - getIntrinsicAttributes().put(AttributeNames.SYNTHETICS_TYPE, - this.getInboundHeaderState().getSyntheticsType()); - getIntrinsicAttributes().put(AttributeNames.SYNTHETICS_INITIATOR, - this.getInboundHeaderState().getSyntheticsInitiator()); getIntrinsicAttributes().put(AttributeNames.SYNTHETICS_VERSION, - this.getInboundHeaderState().getSyntheticsVersion()); - - Map attrsMap = this.getInboundHeaderState().getSyntheticsAttrs(); - String attrName; + String.valueOf(this.getInboundHeaderState().getSyntheticsVersion())); + if (this.getInboundHeaderState().getSyntheticsType() != null) { + getIntrinsicAttributes().put(AttributeNames.SYNTHETICS_TYPE, + this.getInboundHeaderState().getSyntheticsType()); + } + if (this.getInboundHeaderState().getSyntheticsInitiator() != null) { + getIntrinsicAttributes().put(AttributeNames.SYNTHETICS_INITIATOR, + this.getInboundHeaderState().getSyntheticsInitiator()); + } + if (this.getInboundHeaderState().getSyntheticsAttrs() != null) { + Map attrsMap = this.getInboundHeaderState().getSyntheticsAttrs(); + String attrName; - for (String key : attrsMap.keySet()) { - attrName = String.format("synthetics_%s", key); - getIntrinsicAttributes().put(attrName, attrsMap.get(key)); + for (String key : attrsMap.keySet()) { + attrName = String.format("synthetics_%s", key); + getIntrinsicAttributes().put(attrName, attrsMap.get(key)); + } } } diff --git a/newrelic-agent/src/test/java/com/newrelic/agent/TransactionTest.java b/newrelic-agent/src/test/java/com/newrelic/agent/TransactionTest.java index 655adfd5a7..a6bad5990a 100644 --- a/newrelic-agent/src/test/java/com/newrelic/agent/TransactionTest.java +++ b/newrelic-agent/src/test/java/com/newrelic/agent/TransactionTest.java @@ -1496,6 +1496,23 @@ public Map createHeaderMap() { return headerMap; } + public Map createHeaderMapWithoutSynthInfo() { + Map headerMap = new HashMap<>(); + + String synthVal = "[\n" + + " 1,\n" + + " 417446,\n" + + " \"fd09bfa1-bd85-4f8a-9bee-8d51582f5a54\",\n" + + " \"77cbc5dc-327b-4542-90f0-335644134bed\",\n" + + " \"3e5c28ac-7cf3-4faf-ae52-ff36bc93504a\"\n" + + "]"; + String obfuscatedSynthVal = Obfuscator.obfuscateNameUsingKey(synthVal, "anotherExampleKey"); + + headerMap.put("X-NewRelic-Synthetics", obfuscatedSynthVal); + + return headerMap; + } + public InboundHeaders createInboundHeaders(Map map) { Map headerMap = createHeaderMap(); @@ -1515,6 +1532,27 @@ public String getHeader(String name) { }; } + + + public InboundHeaders createInboundHeadersWithoutSyntheticsInfoHeader(Map map) { + Map headerMap = createHeaderMapWithoutSynthInfo(); + + return new InboundHeaders() { + @Override + public HeaderType getHeaderType() { + return HeaderType.HTTP; + } + + @Override + public String getHeader(String name) { + if (headerMap.containsKey(name)) { + return headerMap.get(name); + } + return null; + } + }; + } + private Transaction createTxWithSyntheticsHeaders() throws Exception { Map configMap = createConfigMap(); createServiceManager(configMap); @@ -1531,6 +1569,21 @@ private Transaction createTxWithSyntheticsHeaders() throws Exception { return tx; } + private Transaction createTxWithSyntheticsHeaderWithoutSyntheticsInfoHeader() throws Exception { + Map configMap = createConfigMap(); + createServiceManager(configMap); + InboundHeaders inboundHeaders = createInboundHeadersWithoutSyntheticsInfoHeader(createHeaderMapWithoutSynthInfo()); + Transaction tx = Transaction.getTransaction(true); + Tracer dispatcherTracer = createDispatcherTracer(false); + tx.getTransactionActivity().tracerStarted(dispatcherTracer); + MockHttpRequest httpRequest = new MockHttpRequest(); + MockHttpResponse httpResponse = new MockHttpResponse(); + httpRequest.setHeader("X-NewRelic-Synthetics", inboundHeaders.getHeader("X-NewRelic-Synthetics")); + tx.setRequestAndResponse(httpRequest, httpResponse); + tx.getTransactionActivity().tracerFinished(dispatcherTracer, 0); + return tx; + } + @Test public void testInboundHeaderStateForSyntheticsInformation() throws Exception { @@ -1561,7 +1614,23 @@ public void testTransactionIntrinsicAttrsForSyntheticsInformation() throws Excep assertEquals("scheduled", tx.getIntrinsicAttributes().get("synthetics_type")); assertEquals("Value1", tx.getIntrinsicAttributes().get("synthetics_example1")); assertEquals("Value2", tx.getIntrinsicAttributes().get("synthetics_example2")); - assertEquals(1, tx.getIntrinsicAttributes().get("synthetics_version")); + assertEquals("1", tx.getIntrinsicAttributes().get("synthetics_version")); + } + + @Test + public void testTransactionIntrinsicAttrsWhenNoSyntheticsInfoHeaderIsReceived() throws Exception { + + Transaction tx = createTxWithSyntheticsHeaderWithoutSyntheticsInfoHeader(); + + assertNotNull(tx.getIntrinsicAttributes()); + assertEquals("77cbc5dc-327b-4542-90f0-335644134bed", tx.getIntrinsicAttributes().get("synthetics_job_id")); + assertEquals("fd09bfa1-bd85-4f8a-9bee-8d51582f5a54", tx.getIntrinsicAttributes().get("synthetics_resource_id")); + assertEquals("3e5c28ac-7cf3-4faf-ae52-ff36bc93504a", tx.getIntrinsicAttributes().get("synthetics_monitor_id")); + assertEquals("1", tx.getIntrinsicAttributes().get("synthetics_version")); + assertNull(tx.getIntrinsicAttributes().get("synthetics_initiator")); + assertNull(tx.getIntrinsicAttributes().get("synthetics_type")); + assertNull(tx.getIntrinsicAttributes().get("synthetics_example1")); + assertNull(tx.getIntrinsicAttributes().get("synthetics_example2")); } private Map createNRDTConfigMap(boolean excludeNewRelicHeader) {