232 lines
8.8 KiB
C#
232 lines
8.8 KiB
C#
// <copyright file="ActivityExtensionsTest.cs" company="OpenTelemetry Authors">
|
|
// Copyright The OpenTelemetry Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// </copyright>
|
|
|
|
using System.Diagnostics;
|
|
using Xunit;
|
|
|
|
namespace OpenTelemetry.Trace.Tests
|
|
{
|
|
public class ActivityExtensionsTest
|
|
{
|
|
private const string ActivitySourceName = "test.status";
|
|
private const string ActivityName = "Test Activity";
|
|
|
|
[Fact]
|
|
public void SetStatus()
|
|
{
|
|
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
|
.AddSource(ActivitySourceName)
|
|
.Build();
|
|
|
|
using var source = new ActivitySource(ActivitySourceName);
|
|
using var activity = source.StartActivity(ActivityName);
|
|
activity.SetStatus(Status.Ok);
|
|
activity?.Stop();
|
|
|
|
Assert.Equal(Status.Ok, activity.GetStatus());
|
|
}
|
|
|
|
[Fact]
|
|
public void SetStatusWithDescription()
|
|
{
|
|
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
|
.AddSource(ActivitySourceName)
|
|
.Build();
|
|
|
|
using var source = new ActivitySource(ActivitySourceName);
|
|
using var activity = source.StartActivity(ActivityName);
|
|
activity.SetStatus(Status.Error.WithDescription("Not Found"));
|
|
activity?.Stop();
|
|
|
|
var status = activity.GetStatus();
|
|
Assert.Equal(StatusCode.Error, status.StatusCode);
|
|
Assert.Equal("Not Found", status.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetStatusWithDescriptionTwice()
|
|
{
|
|
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
|
.AddSource(ActivitySourceName)
|
|
.Build();
|
|
|
|
using var source = new ActivitySource(ActivitySourceName);
|
|
using var activity = source.StartActivity(ActivityName);
|
|
activity.SetStatus(Status.Error.WithDescription("Not Found"));
|
|
activity.SetStatus(Status.Ok);
|
|
activity?.Stop();
|
|
|
|
var status = activity.GetStatus();
|
|
Assert.Equal(StatusCode.Ok, status.StatusCode);
|
|
Assert.Null(status.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetStatusWithIgnoredDescription()
|
|
{
|
|
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
|
.AddSource(ActivitySourceName)
|
|
.Build();
|
|
|
|
using var source = new ActivitySource(ActivitySourceName);
|
|
using var activity = source.StartActivity(ActivityName);
|
|
activity.SetStatus(Status.Ok.WithDescription("This should be ignored."));
|
|
activity?.Stop();
|
|
|
|
var status = activity.GetStatus();
|
|
Assert.Equal(StatusCode.Ok, status.StatusCode);
|
|
Assert.Null(status.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetCancelledStatus()
|
|
{
|
|
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
|
.AddSource(ActivitySourceName)
|
|
.Build();
|
|
|
|
using var source = new ActivitySource(ActivitySourceName);
|
|
using var activity = source.StartActivity(ActivityName);
|
|
activity.SetStatus(Status.Error);
|
|
activity?.Stop();
|
|
|
|
Assert.True(activity.GetStatus().StatusCode.Equals(Status.Error.StatusCode));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetStatusWithNoStatusInActivity()
|
|
{
|
|
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
|
.AddSource(ActivitySourceName)
|
|
.Build();
|
|
|
|
using var source = new ActivitySource(ActivitySourceName);
|
|
using var activity = source.StartActivity(ActivityName);
|
|
activity?.Stop();
|
|
|
|
Assert.Equal(Status.Unset, activity.GetStatus());
|
|
}
|
|
|
|
[Fact]
|
|
public void LastSetStatusWins()
|
|
{
|
|
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
|
.AddSource(ActivitySourceName)
|
|
.Build();
|
|
|
|
using var source = new ActivitySource(ActivitySourceName);
|
|
using var activity = source.StartActivity(ActivityName);
|
|
activity.SetStatus(Status.Error);
|
|
activity.SetStatus(Status.Ok);
|
|
activity?.Stop();
|
|
|
|
Assert.Equal(Status.Ok, activity.GetStatus());
|
|
}
|
|
|
|
[Fact]
|
|
public void CheckRecordException()
|
|
{
|
|
var message = "message";
|
|
var exception = new ArgumentNullException(message, new Exception(message));
|
|
using var activity = new Activity("test-activity");
|
|
activity.RecordException(exception);
|
|
|
|
var @event = activity.Events.FirstOrDefault(e => e.Name == SemanticConventions.AttributeExceptionEventName);
|
|
Assert.Equal(message, @event.Tags.FirstOrDefault(t => t.Key == SemanticConventions.AttributeExceptionMessage).Value);
|
|
Assert.Equal("System.ArgumentNullException", @event.Tags.FirstOrDefault(t => t.Key == SemanticConventions.AttributeExceptionType).Value);
|
|
}
|
|
|
|
[Fact]
|
|
public void RecordExceptionWithAdditionalTags()
|
|
{
|
|
var message = "message";
|
|
var exception = new ArgumentNullException(message, new Exception(message));
|
|
using var activity = new Activity("test-activity");
|
|
|
|
var tags = new TagList
|
|
{
|
|
{ "key1", "value1" },
|
|
{ "key2", "value2" },
|
|
};
|
|
|
|
activity.RecordException(exception, tags);
|
|
|
|
// Additional tags passed in override attributes added from the exception
|
|
tags.Add(SemanticConventions.AttributeExceptionMessage, "SomeOtherExceptionMessage");
|
|
tags.Add(SemanticConventions.AttributeExceptionType, "SomeOtherExceptionType");
|
|
|
|
activity.RecordException(exception, tags);
|
|
|
|
var events = activity.Events.ToArray();
|
|
Assert.Equal(2, events.Length);
|
|
|
|
Assert.Equal(SemanticConventions.AttributeExceptionEventName, events[0].Name);
|
|
Assert.Equal(message, events[0].Tags.First(t => t.Key == SemanticConventions.AttributeExceptionMessage).Value);
|
|
Assert.Equal("System.ArgumentNullException", events[0].Tags.First(t => t.Key == SemanticConventions.AttributeExceptionType).Value);
|
|
Assert.Equal("value1", events[0].Tags.First(t => t.Key == "key1").Value);
|
|
Assert.Equal("value2", events[0].Tags.First(t => t.Key == "key2").Value);
|
|
|
|
Assert.Equal(SemanticConventions.AttributeExceptionEventName, events[1].Name);
|
|
Assert.Equal("SomeOtherExceptionMessage", events[1].Tags.First(t => t.Key == SemanticConventions.AttributeExceptionMessage).Value);
|
|
Assert.Equal("SomeOtherExceptionType", events[1].Tags.First(t => t.Key == SemanticConventions.AttributeExceptionType).Value);
|
|
Assert.Equal("value1", events[1].Tags.First(t => t.Key == "key1").Value);
|
|
Assert.Equal("value2", events[1].Tags.First(t => t.Key == "key2").Value);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetTagValueEmpty()
|
|
{
|
|
using var activity = new Activity("Test");
|
|
|
|
Assert.Null(activity.GetTagValue("Tag1"));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetTagValue()
|
|
{
|
|
using var activity = new Activity("Test");
|
|
activity.SetTag("Tag1", "Value1");
|
|
|
|
Assert.Equal("Value1", activity.GetTagValue("Tag1"));
|
|
Assert.Null(activity.GetTagValue("tag1"));
|
|
Assert.Null(activity.GetTagValue("Tag2"));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("Key", "Value", true)]
|
|
[InlineData("CustomTag", null, false)]
|
|
public void TryCheckFirstTag(string tagName, object expectedTagValue, bool expectedResult)
|
|
{
|
|
using var activity = new Activity("Test");
|
|
activity.SetTag("Key", "Value");
|
|
|
|
var result = activity.TryCheckFirstTag(tagName, out var tagValue);
|
|
Assert.Equal(expectedResult, result);
|
|
Assert.Equal(expectedTagValue, tagValue);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryCheckFirstTagReturnsFalseForActivityWithNoTags()
|
|
{
|
|
using var activity = new Activity("Test");
|
|
|
|
var result = activity.TryCheckFirstTag("Key", out var tagValue);
|
|
Assert.False(result);
|
|
Assert.Null(tagValue);
|
|
}
|
|
}
|
|
}
|