Skip to content

Commit

Permalink
feat: Add transaction ID to intrinsic attributes for error events and…
Browse files Browse the repository at this point in the history
… traces regardless of DT/CAT settings (#2341)

* Always include transaction guid in transaction attributes

* Update integration tests
  • Loading branch information
nr-ahemsath committed Mar 15, 2024
1 parent e266b2e commit 1df0342
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 57 deletions.
Expand Up @@ -48,6 +48,7 @@ private void SetIntrinsicAttributes(IAttributeValueCollection attribValues, Immu

_attribDefs.TransactionName.TrySetValue(attribValues, transactionMetricName.PrefixedName);
_attribDefs.TransactionNameForError.TrySetValue(attribValues, transactionMetricName.PrefixedName);
_attribDefs.Guid.TrySetValue(attribValues, immutableTransaction.Guid);

// Duration is just EndTime minus StartTime for non-web transactions and response time otherwise
_attribDefs.Duration.TrySetValue(attribValues, immutableTransaction.ResponseTimeOrDuration);
Expand Down Expand Up @@ -161,7 +162,6 @@ private void SetIntrinsicAttributes(IAttributeValueCollection attribValues, Immu

if (_configurationService.Configuration.DistributedTracingEnabled)
{
_attribDefs.Guid.TrySetValue(attribValues, immutableTransaction.Guid);
_attribDefs.DistributedTraceId.TrySetValue(attribValues, immutableTransaction.TraceId);
_attribDefs.Priority.TrySetValue(attribValues, immutableTransaction.Priority);
_attribDefs.Sampled.TrySetValue(attribValues, immutableTransaction.Sampled);
Expand Down
Expand Up @@ -758,6 +758,11 @@ public static void TransactionEventHasAttributes(IEnumerable<KeyValuePair<string
}

var actualValue = actualAttributes[expectedAttribute.Key] as string;
if (actualValue == null && actualAttributes[expectedAttribute.Key].GetType() == typeof(bool))
{
actualValue = actualAttributes[expectedAttribute.Key].ToString().ToLowerInvariant();
}

if (actualValue != expectedAttribute.Value)
{
builder.AppendFormat("Attribute named {0} in the transaction event had an unexpected value. Expected: {1}, Actual: {2}", expectedAttribute.Key, expectedAttribute.Value, actualValue);
Expand Down
Expand Up @@ -80,25 +80,27 @@ public void Test()
new Assertions.ExpectedMetric { metricName = @"Supportability/Transactions/allOther" },
};

var expectedAttributes = new Dictionary<string, string>
var metrics = _fixture.AgentLog.GetMetrics().ToList();
var errorTraces = _fixture.AgentLog.GetErrorTraces().ToList();
var transactionEvents = _fixture.AgentLog.GetTransactionEvents().ToList();
var errorEvents = _fixture.AgentLog.GetErrorEvents().ToList();

var transactionId = transactionEvents[0].IntrinsicAttributes["guid"].ToString();

var expectedTransactionEventAttributes = new Dictionary<string, string>
{
{ "errorType", "System.Exception" },
{ "errorMessage", "!Exception~Message!" },
{ "error", "true" }
};

var expectedErrorEventAttributes = new Dictionary<string, string>
{
{ "error.class", "System.Exception" },
{ "error.message", "!Exception~Message!" },
{ "guid", transactionId }
};

var expectedErrorTransactionEventAttributes2 = new List<string> { "error" };

var metrics = _fixture.AgentLog.GetMetrics().ToList();
var errorTraces = _fixture.AgentLog.GetErrorTraces().ToList();
var transactionEvents = _fixture.AgentLog.GetTransactionEvents().ToList();
var errorEvents = _fixture.AgentLog.GetErrorEvents().ToList();

NrAssert.Multiple(
() => Assertions.MetricsExist(expectedMetrics, metrics),
() => Assertions.MetricsDoNotExist(unexpectedMetrics, metrics),
Expand All @@ -108,12 +110,12 @@ public void Test()
() => Assert.Equal("System.Exception", errorTraces[0].ExceptionClassName),
() => Assert.Equal("!Exception~Message!", errorTraces[0].Message),
() => Assert.NotEmpty(errorTraces[0].Attributes.StackTrace),
() => Assert.Equal(errorTraces[0].Attributes.IntrinsicAttributes["guid"], transactionId),
() => Assert.True(transactionEvents.Any(), "No transaction events found."),
() => Assert.True(transactionEvents.Count == 1, $"Expected 1 transaction event but found {transactionEvents.Count}"),
() => Assertions.TransactionEventHasAttributes(expectedAttributes, TransactionEventAttributeType.Intrinsic, transactionEvents[0]),
() => Assertions.TransactionEventHasAttributes(expectedTransactionEventAttributes, TransactionEventAttributeType.Intrinsic, transactionEvents[0]),
() => Assert.Single(errorEvents),
() => Assertions.ErrorEventHasAttributes(expectedErrorEventAttributes, EventAttributeType.Intrinsic, errorEvents[0]),
() => Assertions.TransactionEventHasAttributes(expectedErrorTransactionEventAttributes2, TransactionEventAttributeType.Intrinsic, transactionEvents[0])
() => Assertions.ErrorEventHasAttributes(expectedErrorEventAttributes, EventAttributeType.Intrinsic, errorEvents[0])
);
}
}
Expand Down
Expand Up @@ -50,43 +50,43 @@ public void Test()
{
var expectedMetrics = new List<Assertions.ExpectedMetric>
{
// error metrics
new Assertions.ExpectedMetric {metricName = @"Errors/all", callCount = 1},
// error metrics
new Assertions.ExpectedMetric {metricName = @"Errors/all", callCount = 1},
new Assertions.ExpectedMetric {metricName = @"Errors/allWeb", callCount = 1},
new Assertions.ExpectedMetric {metricName = @"Errors/WebTransaction/WebAPI/Values/ThrowException", callCount = 1 },

// other
new Assertions.ExpectedMetric { metricName = @"WebTransaction", callCount = 1 }
// other
new Assertions.ExpectedMetric { metricName = @"WebTransaction", callCount = 1 }
};

var unexpectedMetrics = new List<Assertions.ExpectedMetric>
{
new Assertions.ExpectedMetric { metricName = @"OtherTransaction/all", callCount = 5 },
};

var metrics = _fixture.AgentLog.GetMetrics().ToList();
var errorTrace = _fixture.AgentLog.GetErrorTraces().ToList().FirstOrDefault();
var transactionEvent = _fixture.AgentLog.GetTransactionEvents().ToList().FirstOrDefault();
var errorEvent = _fixture.AgentLog.GetErrorEvents().FirstOrDefault();

var expectedErrorClass = "System.Exception";
var expectedErrorMessage = "ExceptionMessage";
var transactionId = transactionEvent.IntrinsicAttributes["guid"].ToString();

var expectedAttributes = new Dictionary<string, string>
var expectedTransactionEventAttributes = new Dictionary<string, string>
{
{ "errorType", expectedErrorClass },
{ "errorMessage", expectedErrorMessage },
{ "error", "true" },
};


var expectedErrorEventAttributes = new Dictionary<string, string>
{
{ "error.class", expectedErrorClass },
{ "error.message", expectedErrorMessage },
{ "guid", transactionId },
};

var expectedErrorTransactionEventAttributes2 = new List<string> { "error" };

var metrics = _fixture.AgentLog.GetMetrics().ToList();
var errorTrace = _fixture.AgentLog.GetErrorTraces().ToList().FirstOrDefault();
var transactionEvent = _fixture.AgentLog.GetTransactionEvents().ToList().FirstOrDefault();
var errorEvent = _fixture.AgentLog.GetErrorEvents().FirstOrDefault();

NrAssert.Multiple(
() => Assertions.MetricsExist(expectedMetrics, metrics),
() => Assertions.MetricsDoNotExist(unexpectedMetrics, metrics),
Expand All @@ -96,10 +96,10 @@ public void Test()
() => Assert.Equal("WebTransaction/WebAPI/Values/ThrowException", errorTrace.Path),
() => Assert.Equal(expectedErrorClass, errorTrace.ExceptionClassName),
() => Assert.Equal(expectedErrorMessage, errorTrace.Message),
() => Assert.Equal(transactionId, errorTrace.Attributes.IntrinsicAttributes["guid"]),
() => Assert.NotEmpty(errorTrace.Attributes.StackTrace),
() => Assertions.TransactionEventHasAttributes(expectedAttributes, TransactionEventAttributeType.Intrinsic, transactionEvent),
() => Assertions.ErrorEventHasAttributes(expectedErrorEventAttributes, EventAttributeType.Intrinsic, errorEvent),
() => Assertions.TransactionEventHasAttributes(expectedErrorTransactionEventAttributes2, TransactionEventAttributeType.Intrinsic, transactionEvent)
() => Assertions.TransactionEventHasAttributes(expectedTransactionEventAttributes, TransactionEventAttributeType.Intrinsic, transactionEvent),
() => Assertions.ErrorEventHasAttributes(expectedErrorEventAttributes, EventAttributeType.Intrinsic, errorEvent)
);
}
}
Expand Down
Expand Up @@ -52,13 +52,13 @@ public void Test()
{
var expectedMetrics = new List<Assertions.ExpectedMetric>
{
// error metrics
new Assertions.ExpectedMetric {metricName = @"Errors/all", callCount = 2},
// error metrics
new Assertions.ExpectedMetric {metricName = @"Errors/all", callCount = 2},
new Assertions.ExpectedMetric {metricName = @"Errors/allWeb", callCount = 2},
new Assertions.ExpectedMetric {metricName = @"Errors/WebTransaction/WebService/BasicWebService.TestWebService.ThrowException", callCount = 2},

// other
new Assertions.ExpectedMetric {metricName = @"WebTransaction/WebService/BasicWebService.TestWebService.ThrowException", callCount = 2},
// other
new Assertions.ExpectedMetric {metricName = @"WebTransaction/WebService/BasicWebService.TestWebService.ThrowException", callCount = 2},
new Assertions.ExpectedMetric {metricName = @"DotNet/BasicWebService.TestWebService.ThrowException", callCount = 2},
new Assertions.ExpectedMetric {metricName = @"DotNet/BasicWebService.TestWebService.ThrowException", metricScope = "WebTransaction/WebService/BasicWebService.TestWebService.ThrowException", callCount = 2}
};
Expand All @@ -70,10 +70,16 @@ public void Test()
new Assertions.ExpectedMetric { metricName = @"OtherTransaction/all" },
};

var expectedAttributes = new Dictionary<string, string>
var metrics = _fixture.AgentLog.GetMetrics().ToList();
var errorTraces = _fixture.AgentLog.GetErrorTraces().ToList();
var transactionEvents = _fixture.AgentLog.GetTransactionEvents().ToList();
var errorEvents = _fixture.AgentLog.GetErrorEvents();

var expectedTransactonEventAttributes = new Dictionary<string, string>
{
{ "errorType", ExpectedExceptionType },
{ "errorMessage", "Oh no!" },
{ "error", "true" },
};

var expectedErrorEventAttributes = new Dictionary<string, string>
Expand All @@ -82,11 +88,6 @@ public void Test()
{ "error.message", "Oh no!" },
};

var metrics = _fixture.AgentLog.GetMetrics().ToList();
var errorTraces = _fixture.AgentLog.GetErrorTraces().ToList();
var transactionEvents = _fixture.AgentLog.GetTransactionEvents().ToList();
var errorEvents = _fixture.AgentLog.GetErrorEvents();

NrAssert.Multiple(
() => Assertions.MetricsExist(expectedMetrics, metrics),
() => Assertions.MetricsDoNotExist(unexpectedMetrics, metrics),
Expand All @@ -96,16 +97,19 @@ public void Test()
() => Assert.Equal(ExpectedExceptionType, errorTraces[0].ExceptionClassName),
() => Assert.Equal("Oh no!", errorTraces[0].Message),
() => Assert.NotEmpty(errorTraces[0].Attributes.StackTrace),
() => Assert.NotNull(errorTraces[0].Attributes.IntrinsicAttributes["guid"]),
() => Assert.Equal("WebTransaction/WebService/BasicWebService.TestWebService.ThrowException", errorTraces[1].Path),
() => Assert.Equal(ExpectedExceptionType, errorTraces[1].ExceptionClassName),
() => Assert.Equal("Oh no!", errorTraces[1].Message),
() => Assert.NotEmpty(errorTraces[1].Attributes.StackTrace),
() => Assert.NotNull(errorTraces[1].Attributes.IntrinsicAttributes["guid"]),
() => Assert.True(transactionEvents.Any(), "No transaction events found."),
() => Assert.True(transactionEvents.Count == 2, $"Expected 2 transaction event but found {transactionEvents.Count}"),
() => Assertions.TransactionEventHasAttributes(expectedAttributes, TransactionEventAttributeType.Intrinsic, transactionEvents[0]),
() => Assertions.TransactionEventHasAttributes(expectedAttributes, TransactionEventAttributeType.Intrinsic, transactionEvents[1]),
() => Assertions.TransactionEventHasAttributes(expectedTransactonEventAttributes, TransactionEventAttributeType.Intrinsic, transactionEvents[0]),
() => Assertions.TransactionEventHasAttributes(expectedTransactonEventAttributes, TransactionEventAttributeType.Intrinsic, transactionEvents[1]),
() => Assert.Equal(2, errorEvents.Count()),
() => Assertions.ErrorEventHasAttributes(expectedErrorEventAttributes, EventAttributeType.Intrinsic, errorEvents.FirstOrDefault())
() => Assertions.ErrorEventHasAttributes(expectedErrorEventAttributes, EventAttributeType.Intrinsic, errorEvents.FirstOrDefault()),
() => Assert.NotNull(errorEvents.FirstOrDefault().IntrinsicAttributes["guid"])
);
}
}
Expand Down
Expand Up @@ -79,7 +79,6 @@ public void Test()
"parent.account",
"parent.transportType",
"parent.transportDuration",
"guid",
"traceId",
"priority",
"sampled"
Expand Down
Expand Up @@ -127,7 +127,7 @@ public void GetErrorEvent_InTransaction_IfStatusCodeIs404_ContainsCorrectAttribu
NrAssert.Multiple(
() => Assert.That(errorEvent.IsSynthetics, Is.EqualTo(false)),
() => Assert.That(agentAttributes, Has.Length.EqualTo(7)),
() => Assert.That(intrinsicAttributes, Has.Length.EqualTo(7)),
() => Assert.That(intrinsicAttributes, Has.Length.EqualTo(8)),
() => Assert.That(userAttributes, Is.Empty),

() => Assert.That(agentAttributes, Does.Contain("queue_wait_time_ms")),
Expand All @@ -143,6 +143,7 @@ public void GetErrorEvent_InTransaction_IfStatusCodeIs404_ContainsCorrectAttribu
() => Assert.That(intrinsicAttributes, Does.Contain("error.message")),
() => Assert.That(intrinsicAttributes, Does.Contain("queueDuration")),
() => Assert.That(intrinsicAttributes, Does.Contain("transactionName")),
() => Assert.That(intrinsicAttributes, Does.Contain("guid")),
() => Assert.That(intrinsicAttributes, Does.Contain("timestamp")),
() => Assert.That(intrinsicAttributes, Does.Contain("type"))
);
Expand Down Expand Up @@ -170,7 +171,7 @@ public void GetErrorEvent_InTransaction_WithException_ContainsCorrectAttributes(
NrAssert.Multiple(
() => Assert.That(errorEvent.IsSynthetics, Is.EqualTo(false)),
() => Assert.That(agentAttributes, Has.Length.EqualTo(7)),
() => Assert.That(intrinsicAttributes, Has.Length.EqualTo(7)),
() => Assert.That(intrinsicAttributes, Has.Length.EqualTo(8)),
() => Assert.That(userAttributes, Is.Empty),

() => Assert.That(agentAttributes, Does.Contain("queue_wait_time_ms")),
Expand All @@ -186,6 +187,7 @@ public void GetErrorEvent_InTransaction_WithException_ContainsCorrectAttributes(
() => Assert.That(intrinsicAttributes, Does.Contain("error.message")),
() => Assert.That(intrinsicAttributes, Does.Contain("queueDuration")),
() => Assert.That(intrinsicAttributes, Does.Contain("transactionName")),
() => Assert.That(intrinsicAttributes, Does.Contain("guid")),
() => Assert.That(intrinsicAttributes, Does.Contain("timestamp")),
() => Assert.That(intrinsicAttributes, Does.Contain("type"))
);
Expand Down Expand Up @@ -222,7 +224,7 @@ public void GetErrorEvent_InTransaction_WithException_ContainsCorrectAttributes_
() => Assert.That(errorEvent.IsSynthetics, Is.EqualTo(true)),

() => Assert.That(agentAttributes, Has.Length.EqualTo(7)),
() => Assert.That(intrinsicAttributes, Has.Length.EqualTo(16)),
() => Assert.That(intrinsicAttributes, Has.Length.EqualTo(17)),
() => Assert.That(userAttributes, Has.Length.EqualTo(1)),

() => Assert.That(agentAttributes, Does.Contain("queue_wait_time_ms")),
Expand All @@ -238,6 +240,7 @@ public void GetErrorEvent_InTransaction_WithException_ContainsCorrectAttributes_
() => Assert.That(intrinsicAttributes, Does.Contain("error.message")),
() => Assert.That(intrinsicAttributes, Does.Contain("queueDuration")),
() => Assert.That(intrinsicAttributes, Does.Contain("transactionName")),
() => Assert.That(intrinsicAttributes, Does.Contain("guid")),
() => Assert.That(intrinsicAttributes, Does.Contain("timestamp")),
() => Assert.That(intrinsicAttributes, Does.Contain("type")),
() => Assert.That(intrinsicAttributes, Does.Contain("nr.syntheticsJobId")),
Expand Down

0 comments on commit 1df0342

Please sign in to comment.