Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Activity Default IdFormat to W3C #37686

Merged
merged 9 commits into from
Jun 19, 2020
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'net45' And '$(TargetFramework)' != 'netstandard1.1'">
<Compile Include="System\Diagnostics\Activity.Current.net46.cs" />
<Compile Include="System\Diagnostics\LocalAppContextSwitches.cs" />
<Compile Include="$(CommonPath)System\LocalAppContextSwitches.Common.cs">
<Link>Common\System\LocalAppContextSwitches.Common.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Compile Include="System\Diagnostics\Activity.Current.net45.cs" />
Expand Down Expand Up @@ -82,6 +86,9 @@
<Reference Include="System.Threading" />
<Reference Include="System.Resources.ResourceManager" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.3'">
<Reference Include="System.AppContext" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
<Compile Include="AssemblyInfo.netfx.cs" />
<Compile Include="System\Diagnostics\Activity.DateTime.netfx.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public partial class Activity : IDisposable
private static ActivityIdFormat s_defaultIdFormat;
/// <summary>
/// Normally if the ParentID is defined, the format of that is used to determine the
/// format used by the Activity. However if ForceDefaultFormat is set to true, the
/// format used by the Activity. However if ForceDefaultFormat is set to true, the
/// ID format will always be the DefaultIdFormat even if the ParentID is define and is
/// a different format.
/// </summary>
Expand Down Expand Up @@ -735,7 +735,13 @@ public static ActivityIdFormat DefaultIdFormat
get
{
if (s_defaultIdFormat == ActivityIdFormat.Unknown)
{
#if NO_EVENTSOURCE_COMPLEX_TYPE_SUPPORT
tarekgh marked this conversation as resolved.
Show resolved Hide resolved
s_defaultIdFormat = ActivityIdFormat.Hierarchical;
#else
s_defaultIdFormat = LocalAppContextSwitches.DefaultActivityIdFormatIsHierarchial ? ActivityIdFormat.Hierarchical : ActivityIdFormat.W3C;
#endif // NO_EVENTSOURCE_COMPLEX_TYPE_SUPPORT
}
return s_defaultIdFormat;
}
set
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;

namespace System
{
internal static partial class LocalAppContextSwitches
{
private static int s_defaultActivityIdFormatIsHierarchial;
public static bool DefaultActivityIdFormatIsHierarchial
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => GetCachedSwitchValue("System.Diagnostics.DefaultActivityIdFormatIsHierarchial", ref s_defaultActivityIdFormatIsHierarchial);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,6 @@ public void ActivityIdNonHierarchicalOverflow()

Assert.Equal(parentId, activity.ParentId);

// With probability 1/MaxLong, Activity.Id length may be expectedIdLength + 1
Assert.InRange(activity.Id.Length, expectedIdLength, expectedIdLength + 1);
tarekgh marked this conversation as resolved.
Show resolved Hide resolved
Assert.DoesNotContain('#', activity.Id);
}

Expand Down Expand Up @@ -258,6 +256,7 @@ public void IdGenerationNoParent()
public void IdGenerationInternalParent()
{
var parent = new Activity("parent");
parent.SetIdFormat(ActivityIdFormat.Hierarchical);
parent.Start();
var child1 = new Activity("child1");
var child2 = new Activity("child2");
Expand Down Expand Up @@ -539,7 +538,7 @@ public void IdFormat_HierarchicalIsDefault()
{
Activity activity = new Activity("activity1");
activity.Start();
Assert.Equal(ActivityIdFormat.Hierarchical, activity.IdFormat);
Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat);
tarekgh marked this conversation as resolved.
Show resolved Hide resolved
}

[Fact]
Expand Down Expand Up @@ -637,9 +636,9 @@ public void IdFormat_ZeroTraceIdAndSpanIdWithHierarchicalFormat()
{
Activity activity = new Activity("activity");
activity.Start();
Assert.Equal(ActivityIdFormat.Hierarchical, activity.IdFormat);
Assert.Equal("00000000000000000000000000000000", activity.TraceId.ToHexString());
Assert.Equal("0000000000000000", activity.SpanId.ToHexString());
Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat);
Assert.NotEqual("00000000000000000000000000000000", activity.TraceId.ToHexString());
Assert.NotEqual("0000000000000000", activity.SpanId.ToHexString());
tarekgh marked this conversation as resolved.
Show resolved Hide resolved
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Threading.Tasks;
using Xunit;

namespace System.Diagnostics.Tests
{
public class ActivityTests : IDisposable
{
[Fact]
public void ActivityIdNonHierarchicalOverflow()
{
// find out Activity Id length on this platform in this AppDomain
Activity testActivity = new Activity("activity")
.Start();
var expectedIdLength = testActivity.Id.Length;
testActivity.Stop();

// check that if parentId '|aaa...a' 1024 bytes long is set with single node (no dots or underscores in the Id)
// it causes overflow during Id generation, and new root Id is generated for the new Activity
var parentId = '|' + new string('a', 1022) + '.';

var activity = new Activity("activity")
.SetParentId(parentId)
.Start();

Assert.Equal(parentId, activity.ParentId);

// With probability 1/MaxLong, Activity.Id length may be expectedIdLength + 1
Assert.InRange(activity.Id.Length, expectedIdLength, expectedIdLength + 1);
Assert.DoesNotContain('#', activity.Id);
}

[Fact]
public void IdGenerationInternalParent()
{
var parent = new Activity("parent");
parent.Start();
var child1 = new Activity("child1");
var child2 = new Activity("child2");
//start 2 children in different execution contexts
Task.Run(() => child1.Start()).Wait();
Task.Run(() => child2.Start()).Wait();

// In Debug builds of System.Diagnostics.DiagnosticSource, the child operation Id will be constructed as follows
// "|parent.RootId.<child.OperationName.Replace(., -)>-childCount.".
// This is for debugging purposes to know which operation the child Id is comming from.
//
// In Release builds of System.Diagnostics.DiagnosticSource, it will not contain the operation name to keep it simple and it will be as
// "|parent.RootId.childCount.".

string child1DebugString = $"|{parent.RootId}.{child1.OperationName}-1.";
string child2DebugString = $"|{parent.RootId}.{child2.OperationName}-2.";
string child1ReleaseString = $"|{parent.RootId}.1.";
string child2ReleaseString = $"|{parent.RootId}.2.";

AssertExtensions.AtLeastOneEquals(child1DebugString, child1ReleaseString, child1.Id);
AssertExtensions.AtLeastOneEquals(child2DebugString, child2ReleaseString, child2.Id);

Assert.Equal(parent.RootId, child1.RootId);
Assert.Equal(parent.RootId, child2.RootId);
child1.Stop();
child2.Stop();
var child3 = new Activity("child3");
child3.Start();

string child3DebugString = $"|{parent.RootId}.{child3.OperationName}-3.";
string child3ReleaseString = $"|{parent.RootId}.3.";

AssertExtensions.AtLeastOneEquals(child3DebugString, child3ReleaseString, child3.Id);

var grandChild = new Activity("grandChild");
grandChild.Start();

child3DebugString = $"{child3.Id}{grandChild.OperationName}-1.";
child3ReleaseString = $"{child3.Id}1.";

AssertExtensions.AtLeastOneEquals(child3DebugString, child3ReleaseString, grandChild.Id);
}

[Fact]
public void IdFormat_HierarchicalIsDefault()
{
Activity activity = new Activity("activity1");
activity.Start();
Assert.Equal(ActivityIdFormat.Hierarchical, activity.IdFormat);
}

[Fact]
public void IdFormat_ZeroTraceIdAndSpanIdWithHierarchicalFormat()
{
Activity activity = new Activity("activity");
activity.Start();
Assert.Equal(ActivityIdFormat.Hierarchical, activity.IdFormat);
Assert.Equal("00000000000000000000000000000000", activity.TraceId.ToHexString());
Assert.Equal("0000000000000000", activity.SpanId.ToHexString());
}

public void Dispose()
{
Activity.Current = null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
<TestRuntime>true</TestRuntime>
</PropertyGroup>
<ItemGroup>
<Compile Include="ActivityTests.cs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"configProperties": {
"System.Diagnostics.DefaultActivityIdFormatIsHierarchial": true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@
<Compile Include="misc\GDI\DeviceContextType.cs" />
<Compile Include="misc\GDI\WindowsGraphics.cs" />
<Compile Include="misc\GDI\WindowsRegion.cs" />
<Compile Include="$(CoreLibSharedDir)System\LocalAppContextSwitches.Common.cs"
<Compile Include="$(CommonPath)System\LocalAppContextSwitches.Common.cs"
Link="System\LocalAppContextSwitches.Common.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Interop.Libraries.cs"
Link="Common\Interop\Windows\Interop.Libraries.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,6 @@
<Compile Include="$(MSBuildThisFileDirectory)System\LazyOfTTMetadata.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\LoaderOptimization.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\LoaderOptimizationAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\LocalAppContextSwitches.Common.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\LocalAppContextSwitches.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\LocalDataStoreSlot.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MarshalByRefObject.cs" />
Expand Down Expand Up @@ -1061,6 +1060,9 @@
<Compile Include="$(CommonPath)SkipLocalsInit.cs">
<Link>Common\SkipLocalsInit.cs</Link>
</Compile>
<Compile Include="$(CommonPath)System\LocalAppContextSwitches.Common.cs">
<Link>Common\System\LocalAppContextSwitches.Common.cs</Link>
</Compile>
<Compile Include="$(CommonPath)System\HResults.cs">
<Link>Common\System\HResults.cs</Link>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,7 @@
<Compile Include="System\Xml\Xsl\Xslt\XsltLoader.cs" />
<Compile Include="System\Xml\Xsl\Xslt\XsltQilFactory.cs" />
<Compile Include="System\Xml\Xsl\Xslt\XslVisitor.cs" />
<Compile Include="$(CoreLibSharedDir)System\LocalAppContextSwitches.Common.cs"
<Compile Include="$(CommonPath)System\LocalAppContextSwitches.Common.cs"
Link="System\LocalAppContextSwitches.Common.cs" />
<Compile Include="System\Xml\Core\LocalAppContextSwitches.cs" />
<Compile Include="$(CommonPath)System\CSharpHelpers.cs" />
Expand Down