Move all diagnostic source events to a single callback method `OnEventWritten` (#3691)

This commit is contained in:
Vishwesh Bankwar 2022-09-26 12:22:41 -07:00 committed by GitHub
parent ed0450ef0e
commit 8800b2ffdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 280 additions and 300 deletions

View File

@ -32,16 +32,25 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation
internal class HttpInListener : ListenerHandler
{
internal const string ActivityOperationName = "Microsoft.AspNetCore.Hosting.HttpRequestIn";
internal const string OnStartEvent = "Microsoft.AspNetCore.Hosting.HttpRequestIn.Start";
internal const string OnStopEvent = "Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop";
internal const string OnMvcBeforeActionEvent = "Microsoft.AspNetCore.Mvc.BeforeAction";
internal const string OnUnhandledHostingExceptionEvent = "Microsoft.AspNetCore.Hosting.UnhandledException";
internal const string OnUnHandledDiagnosticsExceptionEvent = "Microsoft.AspNetCore.Diagnostics.UnhandledException";
#if NET7_0_OR_GREATER
// https://github.com/dotnet/aspnetcore/blob/8d6554e655b64da75b71e0e20d6db54a3ba8d2fb/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs#L85
internal static readonly string AspNetCoreActivitySourceName = "Microsoft.AspNetCore";
#endif
internal static readonly AssemblyName AssemblyName = typeof(HttpInListener).Assembly.GetName();
internal static readonly string ActivitySourceName = AssemblyName.Name;
internal static readonly Version Version = AssemblyName.Version;
internal static readonly ActivitySource ActivitySource = new(ActivitySourceName, Version.ToString());
private const string DiagnosticSourceName = "Microsoft.AspNetCore";
private const string UnknownHostName = "UNKNOWN-HOST";
private static readonly Func<HttpRequest, string, IEnumerable<string>> HttpRequestHeaderValuesGetter = (request, name) => request.Headers[name];
private readonly PropertyFetcher<Exception> stopExceptionFetcher = new("Exception");
private readonly AspNetCoreInstrumentationOptions options;
@ -54,8 +63,40 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation
this.options = options;
}
public override void OnEventWritten(string name, object payload)
{
switch (name)
{
case OnStartEvent:
{
this.OnStartActivity(Activity.Current, payload);
}
break;
case OnStopEvent:
{
this.OnStopActivity(Activity.Current, payload);
}
break;
case OnMvcBeforeActionEvent:
{
this.OnMvcBeforeAction(Activity.Current, payload);
}
break;
case OnUnhandledHostingExceptionEvent:
case OnUnHandledDiagnosticsExceptionEvent:
{
this.OnException(Activity.Current, payload);
}
break;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "The objects should not be disposed.")]
public override void OnStartActivity(Activity activity, object payload)
public void OnStartActivity(Activity activity, object payload)
{
// The overall flow of what AspNetCore library does is as below:
// Activity.Start()
@ -179,7 +220,7 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation
}
}
public override void OnStopActivity(Activity activity, object payload)
public void OnStopActivity(Activity activity, object payload)
{
if (activity.IsAllDataRequested)
{
@ -239,55 +280,52 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation
}
}
public override void OnCustom(string name, Activity activity, object payload)
public void OnMvcBeforeAction(Activity activity, object payload)
{
if (name == "Microsoft.AspNetCore.Mvc.BeforeAction")
// We cannot rely on Activity.Current here
// There could be activities started by middleware
// after activity started by framework resulting in different Activity.Current.
// so, we need to first find the activity started by Asp.Net Core.
// For .net6.0 onwards we could use IHttpActivityFeature to get the activity created by framework
// var httpActivityFeature = context.Features.Get<IHttpActivityFeature>();
// activity = httpActivityFeature.Activity;
// However, this will not work as in case of custom propagator
// we start a new activity during onStart event which is a sibling to the activity created by framework
// So, in that case we need to get the activity created by us here.
// we can do so only by looping through activity.Parent chain.
while (activity != null)
{
// We cannot rely on Activity.Current here
// There could be activities started by middleware
// after activity started by framework resulting in different Activity.Current.
// so, we need to first find the activity started by Asp.Net Core.
// For .net6.0 onwards we could use IHttpActivityFeature to get the activity created by framework
// var httpActivityFeature = context.Features.Get<IHttpActivityFeature>();
// activity = httpActivityFeature.Activity;
// However, this will not work as in case of custom propagator
// we start a new activity during onStart event which is a sibling to the activity created by framework
// So, in that case we need to get the activity created by us here.
// we can do so only by looping through activity.Parent chain.
while (activity != null)
if (string.Equals(activity.OperationName, ActivityOperationName, StringComparison.Ordinal))
{
if (string.Equals(activity.OperationName, ActivityOperationName, StringComparison.Ordinal))
{
break;
}
activity = activity.Parent;
break;
}
if (activity == null)
activity = activity.Parent;
}
if (activity == null)
{
return;
}
if (activity.IsAllDataRequested)
{
var beforeActionEventData = payload as BeforeActionEventData;
var template = beforeActionEventData.ActionDescriptor?.AttributeRouteInfo?.Template;
if (!string.IsNullOrEmpty(template))
{
return;
// override the span name that was previously set to the path part of URL.
activity.DisplayName = template;
activity.SetTag(SemanticConventions.AttributeHttpRoute, template);
}
if (activity.IsAllDataRequested)
{
var beforeActionEventData = payload as BeforeActionEventData;
var template = beforeActionEventData.ActionDescriptor?.AttributeRouteInfo?.Template;
if (!string.IsNullOrEmpty(template))
{
// override the span name that was previously set to the path part of URL.
activity.DisplayName = template;
activity.SetTag(SemanticConventions.AttributeHttpRoute, template);
}
// TODO: Should we get values from RouteData?
// private readonly PropertyFetcher beforeActionRouteDataFetcher = new PropertyFetcher("routeData");
// var routeData = this.beforeActionRouteDataFetcher.Fetch(payload) as RouteData;
}
// TODO: Should we get values from RouteData?
// private readonly PropertyFetcher beforeActionRouteDataFetcher = new PropertyFetcher("routeData");
// var routeData = this.beforeActionRouteDataFetcher.Fetch(payload) as RouteData;
}
}
public override void OnException(Activity activity, object payload)
public void OnException(Activity activity, object payload)
{
if (activity.IsAllDataRequested)
{

View File

@ -24,6 +24,8 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation
{
internal class HttpInMetricsListener : ListenerHandler
{
private const string OnStopEvent = "Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop";
private readonly Meter meter;
private readonly Histogram<double> httpServerDuration;
@ -34,65 +36,68 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation
this.httpServerDuration = meter.CreateHistogram<double>("http.server.duration", "ms", "measures the duration of the inbound HTTP request");
}
public override void OnStopActivity(Activity activity, object payload)
public override void OnEventWritten(string name, object payload)
{
HttpContext context = payload as HttpContext;
if (context == null)
if (name == OnStopEvent)
{
AspNetCoreInstrumentationEventSource.Log.NullPayload(nameof(HttpInMetricsListener), nameof(this.OnStopActivity));
return;
}
// TODO: Prometheus pulls metrics by invoking the /metrics endpoint. Decide if it makes sense to suppress this.
// Below is just a temporary way of achieving this suppression for metrics (we should consider suppressing traces too).
// If we want to suppress activity from Prometheus then we should use SuppressInstrumentationScope.
if (context.Request.Path.HasValue && context.Request.Path.Value.Contains("metrics"))
{
return;
}
string host;
if (context.Request.Host.Port is null or 80 or 443)
{
host = context.Request.Host.Host;
}
else
{
host = context.Request.Host.Host + ":" + context.Request.Host.Port;
}
TagList tags;
var target = (context.GetEndpoint() as RouteEndpoint)?.RoutePattern.RawText;
// TODO: This is just a minimal set of attributes. See the spec for additional attributes:
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#http-server
if (!string.IsNullOrEmpty(target))
{
tags = new TagList
HttpContext context = payload as HttpContext;
if (context == null)
{
{ SemanticConventions.AttributeHttpFlavor, HttpTagHelper.GetFlavorTagValueFromProtocol(context.Request.Protocol) },
{ SemanticConventions.AttributeHttpScheme, context.Request.Scheme },
{ SemanticConventions.AttributeHttpMethod, context.Request.Method },
{ SemanticConventions.AttributeHttpHost, host },
{ SemanticConventions.AttributeHttpTarget, target },
{ SemanticConventions.AttributeHttpStatusCode, context.Response.StatusCode.ToString() },
};
}
else
{
tags = new TagList
{
{ SemanticConventions.AttributeHttpFlavor, HttpTagHelper.GetFlavorTagValueFromProtocol(context.Request.Protocol) },
{ SemanticConventions.AttributeHttpScheme, context.Request.Scheme },
{ SemanticConventions.AttributeHttpMethod, context.Request.Method },
{ SemanticConventions.AttributeHttpHost, host },
{ SemanticConventions.AttributeHttpStatusCode, context.Response.StatusCode.ToString() },
};
}
AspNetCoreInstrumentationEventSource.Log.NullPayload(nameof(HttpInMetricsListener), nameof(this.OnEventWritten));
return;
}
this.httpServerDuration.Record(activity.Duration.TotalMilliseconds, tags);
// TODO: Prometheus pulls metrics by invoking the /metrics endpoint. Decide if it makes sense to suppress this.
// Below is just a temporary way of achieving this suppression for metrics (we should consider suppressing traces too).
// If we want to suppress activity from Prometheus then we should use SuppressInstrumentationScope.
if (context.Request.Path.HasValue && context.Request.Path.Value.Contains("metrics"))
{
return;
}
string host;
if (context.Request.Host.Port is null or 80 or 443)
{
host = context.Request.Host.Host;
}
else
{
host = context.Request.Host.Host + ":" + context.Request.Host.Port;
}
TagList tags;
var target = (context.GetEndpoint() as RouteEndpoint)?.RoutePattern.RawText;
// TODO: This is just a minimal set of attributes. See the spec for additional attributes:
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#http-server
if (!string.IsNullOrEmpty(target))
{
tags = new TagList
{
{ SemanticConventions.AttributeHttpFlavor, HttpTagHelper.GetFlavorTagValueFromProtocol(context.Request.Protocol) },
{ SemanticConventions.AttributeHttpScheme, context.Request.Scheme },
{ SemanticConventions.AttributeHttpMethod, context.Request.Method },
{ SemanticConventions.AttributeHttpHost, host },
{ SemanticConventions.AttributeHttpTarget, target },
{ SemanticConventions.AttributeHttpStatusCode, context.Response.StatusCode.ToString() },
};
}
else
{
tags = new TagList
{
{ SemanticConventions.AttributeHttpFlavor, HttpTagHelper.GetFlavorTagValueFromProtocol(context.Request.Protocol) },
{ SemanticConventions.AttributeHttpScheme, context.Request.Scheme },
{ SemanticConventions.AttributeHttpMethod, context.Request.Method },
{ SemanticConventions.AttributeHttpHost, host },
{ SemanticConventions.AttributeHttpStatusCode, context.Response.StatusCode.ToString() },
};
}
this.httpServerDuration.Record(Activity.Current.Duration.TotalMilliseconds, tags);
}
}
}
}

View File

@ -31,6 +31,9 @@ namespace OpenTelemetry.Instrumentation.GrpcNetClient.Implementation
internal static readonly Version Version = AssemblyName.Version;
internal static readonly ActivitySource ActivitySource = new(ActivitySourceName, Version.ToString());
private const string OnStartEvent = "Grpc.Net.Client.GrpcOut.Start";
private const string OnStopEvent = "Grpc.Net.Client.GrpcOut.Stop";
private readonly GrpcClientInstrumentationOptions options;
private readonly PropertyFetcher<HttpRequestMessage> startRequestFetcher = new("Request");
private readonly PropertyFetcher<HttpResponseMessage> stopRequestFetcher = new("Response");
@ -41,7 +44,26 @@ namespace OpenTelemetry.Instrumentation.GrpcNetClient.Implementation
this.options = options;
}
public override void OnStartActivity(Activity activity, object payload)
public override void OnEventWritten(string name, object payload)
{
switch (name)
{
case OnStartEvent:
{
this.OnStartActivity(Activity.Current, payload);
}
break;
case OnStopEvent:
{
this.OnStopActivity(Activity.Current, payload);
}
break;
}
}
public void OnStartActivity(Activity activity, object payload)
{
// The overall flow of what GrpcClient library does is as below:
// Activity.Start()
@ -137,7 +159,7 @@ namespace OpenTelemetry.Instrumentation.GrpcNetClient.Implementation
}
}
public override void OnStopActivity(Activity activity, object payload)
public void OnStopActivity(Activity activity, object payload)
{
if (activity.IsAllDataRequested)
{

View File

@ -35,6 +35,10 @@ namespace OpenTelemetry.Instrumentation.Http.Implementation
internal static readonly Version Version = AssemblyName.Version;
internal static readonly ActivitySource ActivitySource = new(ActivitySourceName, Version.ToString());
private const string OnStartEvent = "System.Net.Http.HttpRequestOut.Start";
private const string OnStopEvent = "System.Net.Http.HttpRequestOut.Stop";
private const string OnUnhandledExceptionEvent = "System.Net.Http.Exception";
private readonly PropertyFetcher<HttpRequestMessage> startRequestFetcher = new("Request");
private readonly PropertyFetcher<HttpResponseMessage> stopResponseFetcher = new("Response");
private readonly PropertyFetcher<Exception> stopExceptionFetcher = new("Exception");
@ -59,7 +63,32 @@ namespace OpenTelemetry.Instrumentation.Http.Implementation
this.options = options;
}
public override void OnStartActivity(Activity activity, object payload)
public override void OnEventWritten(string name, object payload)
{
switch (name)
{
case OnStartEvent:
{
this.OnStartActivity(Activity.Current, payload);
}
break;
case OnStopEvent:
{
this.OnStopActivity(Activity.Current, payload);
}
break;
case OnUnhandledExceptionEvent:
{
this.OnException(Activity.Current, payload);
}
break;
}
}
public void OnStartActivity(Activity activity, object payload)
{
// The overall flow of what HttpClient library does is as below:
// Activity.Start()
@ -148,7 +177,7 @@ namespace OpenTelemetry.Instrumentation.Http.Implementation
}
}
public override void OnStopActivity(Activity activity, object payload)
public void OnStopActivity(Activity activity, object payload)
{
// For .NET7.0 or higher versions, activity is created using activity source
// However, the framework will fallback to creating activity if the sampler's decision is to drop and there is a active diagnostic listener.
@ -206,7 +235,7 @@ namespace OpenTelemetry.Instrumentation.Http.Implementation
}
}
public override void OnException(Activity activity, object payload)
public void OnException(Activity activity, object payload)
{
// For .NET7.0 or higher versions, activity is created using activity source
// However, the framework will fallback to creating activity if the sampler's decision is to drop and there is a active diagnostic listener.

View File

@ -24,6 +24,8 @@ namespace OpenTelemetry.Instrumentation.Http.Implementation
{
internal class HttpHandlerMetricsDiagnosticListener : ListenerHandler
{
internal const string OnStopEvent = "System.Net.Http.HttpRequestOut.Stop";
private readonly PropertyFetcher<HttpResponseMessage> stopResponseFetcher = new("Response");
private readonly Histogram<double> httpClientDuration;
@ -33,28 +35,32 @@ namespace OpenTelemetry.Instrumentation.Http.Implementation
this.httpClientDuration = meter.CreateHistogram<double>("http.client.duration", "ms", "measures the duration of the outbound HTTP request");
}
public override void OnStopActivity(Activity activity, object payload)
public override void OnEventWritten(string name, object payload)
{
if (Sdk.SuppressInstrumentation)
if (name == OnStopEvent)
{
return;
}
if (this.stopResponseFetcher.TryFetch(payload, out HttpResponseMessage response) && response != null)
{
var request = response.RequestMessage;
// TODO: This is just a minimal set of attributes. See the spec for additional attributes:
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#http-client
var tags = new KeyValuePair<string, object>[]
if (Sdk.SuppressInstrumentation)
{
new KeyValuePair<string, object>(SemanticConventions.AttributeHttpMethod, HttpTagHelper.GetNameForHttpMethod(request.Method)),
new KeyValuePair<string, object>(SemanticConventions.AttributeHttpScheme, request.RequestUri.Scheme),
new KeyValuePair<string, object>(SemanticConventions.AttributeHttpStatusCode, (int)response.StatusCode),
new KeyValuePair<string, object>(SemanticConventions.AttributeHttpFlavor, HttpTagHelper.GetFlavorTagValueFromProtocolVersion(request.Version)),
};
return;
}
this.httpClientDuration.Record(activity.Duration.TotalMilliseconds, tags);
var activity = Activity.Current;
if (this.stopResponseFetcher.TryFetch(payload, out HttpResponseMessage response) && response != null)
{
var request = response.RequestMessage;
// TODO: This is just a minimal set of attributes. See the spec for additional attributes:
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#http-client
var tags = new KeyValuePair<string, object>[]
{
new KeyValuePair<string, object>(SemanticConventions.AttributeHttpMethod, HttpTagHelper.GetNameForHttpMethod(request.Method)),
new KeyValuePair<string, object>(SemanticConventions.AttributeHttpScheme, request.RequestUri.Scheme),
new KeyValuePair<string, object>(SemanticConventions.AttributeHttpStatusCode, (int)response.StatusCode),
new KeyValuePair<string, object>(SemanticConventions.AttributeHttpFlavor, HttpTagHelper.GetFlavorTagValueFromProtocolVersion(request.Version)),
};
this.httpClientDuration.Record(activity.Duration.TotalMilliseconds, tags);
}
}
}
}

View File

@ -49,8 +49,9 @@ namespace OpenTelemetry.Instrumentation.SqlClient.Implementation
public override bool SupportsNullActivity => true;
public override void OnCustom(string name, Activity activity, object payload)
public override void OnEventWritten(string name, object payload)
{
var activity = Activity.Current;
switch (name)
{
case SqlDataBeforeExecuteCommand:

View File

@ -49,22 +49,7 @@ namespace OpenTelemetry.Instrumentation
try
{
if (value.Key.EndsWith("Start", StringComparison.Ordinal))
{
this.handler.OnStartActivity(Activity.Current, value.Value);
}
else if (value.Key.EndsWith("Stop", StringComparison.Ordinal))
{
this.handler.OnStopActivity(Activity.Current, value.Value);
}
else if (value.Key.EndsWith("Exception", StringComparison.Ordinal))
{
this.handler.OnException(Activity.Current, value.Value);
}
else
{
this.handler.OnCustom(value.Key, Activity.Current, value.Value);
}
this.handler.OnEventWritten(value.Key, value.Value);
}
catch (Exception ex)
{

View File

@ -41,40 +41,12 @@ namespace OpenTelemetry.Instrumentation
/// </summary>
public virtual bool SupportsNullActivity { get; }
/// <summary>
/// Method called for an event with the suffix 'Start'.
/// </summary>
/// <param name="activity">The <see cref="Activity"/> to be started.</param>
/// <param name="payload">An object that represent the value being passed as a payload for the event.</param>
public virtual void OnStartActivity(Activity activity, object payload)
{
}
/// <summary>
/// Method called for an event with the suffix 'Stop'.
/// </summary>
/// <param name="activity">The <see cref="Activity"/> to be stopped.</param>
/// <param name="payload">An object that represent the value being passed as a payload for the event.</param>
public virtual void OnStopActivity(Activity activity, object payload)
{
}
/// <summary>
/// Method called for an event with the suffix 'Exception'.
/// </summary>
/// <param name="activity">The <see cref="Activity"/>.</param>
/// <param name="payload">An object that represent the value being passed as a payload for the event.</param>
public virtual void OnException(Activity activity, object payload)
{
}
/// <summary>
/// Method called for an event which does not have 'Start', 'Stop' or 'Exception' as suffix.
/// </summary>
/// <param name="name">Custom name.</param>
/// <param name="activity">The <see cref="Activity"/> to be processed.</param>
/// <param name="payload">An object that represent the value being passed as a payload for the event.</param>
public virtual void OnCustom(string name, Activity activity, object payload)
public virtual void OnEventWritten(string name, object payload)
{
}
}

View File

@ -466,14 +466,24 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
.AddAspNetCoreInstrumentation(new AspNetCoreInstrumentation(
new TestHttpInListener(new AspNetCoreInstrumentationOptions())
{
OnStartActivityCallback = (activity, payload) =>
OnEventWrittenCallback = (name, payload) =>
{
baggageCountAfterStart = Baggage.Current.Count;
},
OnStopActivityCallback = (activity, payload) =>
{
baggageCountAfterStop = Baggage.Current.Count;
stopSignal.Set();
switch (name)
{
case HttpInListener.OnStartEvent:
{
baggageCountAfterStart = Baggage.Current.Count;
}
break;
case HttpInListener.OnStopEvent:
{
baggageCountAfterStop = Baggage.Current.Count;
stopSignal.Set();
}
break;
}
},
}))
.Build();
@ -625,7 +635,7 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
Assert.Equal(activityName, middlewareActivity.OperationName);
Assert.Equal(activityName, middlewareActivity.DisplayName);
// tag http.route should not be added on activity started by asp.net core as it will not be found during oncustom event
// tag http.route should not be added on activity started by asp.net core as it will not be found during OnEventWritten event
Assert.DoesNotContain(aspnetcoreframeworkactivity.TagObjects, t => t.Key == SemanticConventions.AttributeHttpRoute);
Assert.Equal("Microsoft.AspNetCore.Hosting.HttpRequestIn", aspnetcoreframeworkactivity.OperationName);
Assert.Equal("/api/values/2", aspnetcoreframeworkactivity.DisplayName);
@ -707,10 +717,18 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
.AddAspNetCoreInstrumentation(new AspNetCoreInstrumentation(
new TestHttpInListener(new AspNetCoreInstrumentationOptions())
{
OnCustomCallback = (name, activity, payload) =>
OnEventWrittenCallback = (name, payload) =>
{
actualCustomEventName = name;
numberOfCustomCallbacks++;
switch (name)
{
case HttpInListener.OnMvcBeforeActionEvent:
{
actualCustomEventName = name;
numberOfCustomCallbacks++;
}
break;
}
},
}))
.Build();
@ -742,9 +760,20 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
.AddAspNetCoreInstrumentation(new AspNetCoreInstrumentation(
new TestHttpInListener(new AspNetCoreInstrumentationOptions())
{
OnExceptionCallback = (activity, payload) =>
OnEventWrittenCallback = (name, payload) =>
{
numberOfExceptionCallbacks++;
switch (name)
{
// TODO: Add test case for validating name for both the types
// of exception event.
case HttpInListener.OnUnhandledHostingExceptionEvent:
case HttpInListener.OnUnHandledDiagnosticsExceptionEvent:
{
numberOfExceptionCallbacks++;
}
break;
}
},
}))
.Build();
@ -782,9 +811,18 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
.AddAspNetCoreInstrumentation(new AspNetCoreInstrumentation(
new TestHttpInListener(new AspNetCoreInstrumentationOptions())
{
OnExceptionCallback = (activity, payload) =>
OnEventWrittenCallback = (name, payload) =>
{
numberOfExceptionCallbacks++;
switch (name)
{
case HttpInListener.OnUnhandledHostingExceptionEvent:
case HttpInListener.OnUnHandledDiagnosticsExceptionEvent:
{
numberOfExceptionCallbacks++;
}
break;
}
},
}))
.Build();
@ -954,45 +992,18 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
private class TestHttpInListener : HttpInListener
{
public Action<Activity, object> OnStartActivityCallback;
public Action<Activity, object> OnStopActivityCallback;
public Action<Activity, object> OnExceptionCallback;
public Action<string, Activity, object> OnCustomCallback;
public Action<string, object> OnEventWrittenCallback;
public TestHttpInListener(AspNetCoreInstrumentationOptions options)
: base(options)
{
}
public override void OnStartActivity(Activity activity, object payload)
public override void OnEventWritten(string name, object payload)
{
base.OnStartActivity(activity, payload);
base.OnEventWritten(name, payload);
this.OnStartActivityCallback?.Invoke(activity, payload);
}
public override void OnStopActivity(Activity activity, object payload)
{
base.OnStopActivity(activity, payload);
this.OnStopActivityCallback?.Invoke(activity, payload);
}
public override void OnCustom(string name, Activity activity, object payload)
{
base.OnCustom(name, activity, payload);
this.OnCustomCallback?.Invoke(name, activity, payload);
}
public override void OnException(Activity activity, object payload)
{
base.OnException(activity, payload);
this.OnExceptionCallback?.Invoke(activity, payload);
this.OnEventWrittenCallback?.Invoke(name, payload);
}
}
@ -1013,7 +1024,7 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
// Setting the host activity i.e. activity started by asp.net core
// to null here will have no impact on middleware activity.
// This also means that asp.net core activity will not be found
// during OnCustom event.
// during OnEventWritten event.
Activity.Current = null;
this.activity = this.activitySource.StartActivity(this.activityName);
}

View File

@ -1,36 +0,0 @@
// <copyright file="DiagnosticSourceListenerTest.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;
namespace OpenTelemetry.Instrumentation.Tests
{
public class DiagnosticSourceListenerTest
{
private const string TestSourceName = "TestSourceName";
private readonly DiagnosticSource diagnosticSource;
private readonly TestListenerHandler testListenerHandler;
private readonly DiagnosticSourceSubscriber testDiagnosticSourceSubscriber;
public DiagnosticSourceListenerTest()
{
this.diagnosticSource = new DiagnosticListener(TestSourceName);
this.testListenerHandler = new TestListenerHandler(TestSourceName);
this.testDiagnosticSourceSubscriber = new DiagnosticSourceSubscriber(this.testListenerHandler, null);
this.testDiagnosticSourceSubscriber.Subscribe();
}
}
}

View File

@ -1,53 +0,0 @@
// <copyright file="TestListenerHandler.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;
namespace OpenTelemetry.Instrumentation.Tests
{
internal class TestListenerHandler : ListenerHandler
{
public int OnStartInvokedCount = 0;
public int OnStopInvokedCount = 0;
public int OnExceptionInvokedCount = 0;
public int OnCustomInvokedCount = 0;
public TestListenerHandler(string sourceName)
: base(sourceName)
{
}
public override void OnStartActivity(Activity activity, object payload)
{
this.OnStartInvokedCount++;
}
public override void OnStopActivity(Activity activity, object payload)
{
this.OnStopInvokedCount++;
}
public override void OnException(Activity activity, object payload)
{
this.OnExceptionInvokedCount++;
}
public override void OnCustom(string name, Activity activity, object payload)
{
this.OnCustomInvokedCount++;
}
}
}