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

Reworked Open-Telemetry Defaults #4613

Merged
merged 5 commits into from
Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 86 additions & 3 deletions src/HotChocolate/Diagnostics/src/Diagnostics/ActivityEnricher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
namespace HotChocolate.Diagnostics;

/// <summary>
/// The activity enricher is used to add information to the activity spans.
/// You can inherit from this class and override the enricher methods to provide more or
/// The activity enricher is used to add information to the activity spans.
/// You can inherit from this class and override the enricher methods to provide more or
/// less information.
/// </summary>
public class ActivityEnricher
Expand Down Expand Up @@ -330,7 +330,14 @@ public virtual void EnrichFromatHttpResponse(HttpContext context, Activity activ

public virtual void EnrichExecuteRequest(IRequestContext context, Activity activity)
{
activity.DisplayName = context.Operation?.Name?.Value ?? "Execute Request";
var operationDisplayName = CreateOperationDisplayName(context);

if (_options.RenameRootActivity && operationDisplayName is not null)
{
UpdateRootActivityName(activity, operationDisplayName);
}

activity.DisplayName = operationDisplayName ?? "Execute Request";
activity.SetTag("graphql.document.id", context.DocumentId);
activity.SetTag("graphql.document.hash", context.DocumentHash);
activity.SetTag("graphql.document.valid", context.IsValidDocument);
Expand All @@ -350,6 +357,82 @@ public virtual void EnrichExecuteRequest(IRequestContext context, Activity activ
}
}

protected virtual string? CreateOperationDisplayName(IRequestContext context)
{
if (context.Operation is { } operation)
{
StringBuilder displayName = StringBuilderPool.Get();

try
{
var rootSelectionSet = operation.GetRootSelectionSet();

displayName.Append('{');
displayName.Append(' ');

foreach (var selection in rootSelectionSet.Selections.Take(3))
{
if (displayName.Length > 2)
{
displayName.Append(',');
displayName.Append(' ');
}

displayName.Append(selection.ResponseName);
}

if (rootSelectionSet.Selections.Count > 3)
{
displayName.Append(' ');
displayName.Append('.');
displayName.Append('.');
displayName.Append('.');
}

displayName.Append(' ');
displayName.Append('}');

if (operation.Name is { } name)
{
displayName.Insert(0, ' ');
displayName.Insert(0, name.Value);
}

displayName.Insert(0, ' ');
displayName.Insert(0, operation.Definition.Operation.ToString().ToLowerInvariant());

return displayName.ToString();
}
finally
{
StringBuilderPool.Return(displayName);
}
}

return null;
}

private void UpdateRootActivityName(Activity activity, string operationDisplayName)
{
Activity current = activity;

while (current.Parent is not null)
{
current = current.Parent;
}

if (current != activity)
{
current.DisplayName = CreateRootActivityName(activity, current, operationDisplayName);
}
}

protected virtual string CreateRootActivityName(
Activity activity,
Activity root,
string operationDisplayName)
=> $"{root.DisplayName}: {operationDisplayName}";

public virtual void EnrichParseDocument(IRequestContext context, Activity activity)
{
activity.DisplayName = "Parse Document";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public sealed class InstrumentationOptions
/// </summary>
public bool IncludeDocument { get; set; }

/// <summary>
/// Defines if the operation display name shall be included in the root activity.
/// </summary>
public bool RenameRootActivity { get; set; }

internal bool IncludeRequestDetails => RequestDetails is not RequestDetails.None;

internal bool SkipExecuteHttpRequest => (Scopes & ExecuteHttpRequest) != ExecuteHttpRequest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public static IDisposable CaptureActivities(out object activities)
}
};
listener.ActivityStopped = SerializeActivity;
listener.Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllData;
listener.Sample = (ref ActivityCreationOptions<ActivityContext> _) =>
ActivitySamplingResult.AllData;
ActivitySource.AddActivityListener(listener);

rootActivity = HotChocolateActivitySource.Source.StartActivity()!;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using ChilliCream.Testing;
using HotChocolate.Execution;
using Microsoft.Extensions.DependencyInjection;
using Snapshooter.Xunit;
using Xunit;
using static HotChocolate.Diagnostics.ActivityTestHelper;
Expand All @@ -28,6 +29,111 @@ public async Task Track_events_of_a_simple_query_default()
}
}

[Fact]
public async Task Track_events_of_a_simple_query_default_rename_root()
{
using (CaptureActivities(out var activities))
{
// arrange & act
await new ServiceCollection()
.AddGraphQL()
.AddInstrumentation(o =>
{
o.RenameRootActivity = true;
o.Scopes = ActivityScopes.All;
})
.AddQueryType<SimpleQuery>()
.ExecuteRequestAsync("{ sayHello }");

// assert
Assert.Equal("CaptureActivities: query { sayHello }", Activity.Current!.DisplayName);
}
}

[Fact]
public async Task Create_operation_display_name_with_1_field()
{
using (CaptureActivities(out var activities))
{
// arrange & act
await new ServiceCollection()
.AddGraphQL()
.AddInstrumentation(o =>
{
o.RenameRootActivity = true;
o.Scopes = ActivityScopes.All;
})
.AddQueryType<SimpleQuery>()
.ExecuteRequestAsync("{ a: sayHello }");

// assert
activities.MatchSnapshot();
}
}

[Fact]
public async Task Create_operation_display_name_with_1_field_and_op()
{
using (CaptureActivities(out var activities))
{
// arrange & act
await new ServiceCollection()
.AddGraphQL()
.AddInstrumentation(o =>
{
o.RenameRootActivity = true;
o.Scopes = ActivityScopes.All;
})
.AddQueryType<SimpleQuery>()
.ExecuteRequestAsync("query GetA { a: sayHello }");

// assert
activities.MatchSnapshot();
}
}

[Fact]
public async Task Create_operation_display_name_with_3_field()
{
using (CaptureActivities(out var activities))
{
// arrange & act
await new ServiceCollection()
.AddGraphQL()
.AddInstrumentation(o =>
{
o.RenameRootActivity = true;
o.Scopes = ActivityScopes.All;
})
.AddQueryType<SimpleQuery>()
.ExecuteRequestAsync("{ a: sayHello b: sayHello c: sayHello }");

// assert
activities.MatchSnapshot();
}
}

[Fact]
public async Task Create_operation_display_name_with_4_field()
{
using (CaptureActivities(out var activities))
{
// arrange & act
await new ServiceCollection()
.AddGraphQL()
.AddInstrumentation(o =>
{
o.RenameRootActivity = true;
o.Scopes = ActivityScopes.All;
})
.AddQueryType<SimpleQuery>()
.ExecuteRequestAsync("{ a: sayHello b: sayHello c: sayHello d: sayHello }");

// assert
activities.MatchSnapshot();
}
}

[Fact]
public async Task Track_events_of_a_simple_query_detailed()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using HotChocolate.AspNetCore.Utilities;
using Snapshooter.Xunit;
using Xunit;
using static HotChocolate.Diagnostics.ActivityTestHelper;
using System;
using System.Net.Http;

namespace HotChocolate.Diagnostics;


[Collection("Instrumentation")]
public class ServerInstrumentationTests : ServerTestBase
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"activities": [
{
"OperationName": "ExecuteRequest",
"DisplayName": "SayHelloOperation",
"DisplayName": "query SayHelloOperation { sayHello }",
"Status": "Unset",
"tags": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"activities": [
{
"OperationName": "ExecuteRequest",
"DisplayName": "SayHelloOperation",
"DisplayName": "query SayHelloOperation { causeFatalError }",
"Status": "Error",
"tags": [
{
Expand Down
Loading