Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 28b6bbf

Browse files
author
Liudmila Molkova
committed
Start Activity and inject headers in HttpHAndlerDiagnosticListener on Net46
1 parent 0ad9477 commit 28b6bbf

File tree

2 files changed

+436
-209
lines changed

2 files changed

+436
-209
lines changed

src/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs

Lines changed: 54 additions & 14 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -8,6 +8,7 @@
8
using System.Reflection;
8
using System.Reflection;
9
using System.Reflection.Emit;
9
using System.Reflection.Emit;
10
using System.Runtime.Serialization;
10
using System.Runtime.Serialization;
11+
using System.Text;
11

12

12
// This HttpHandlerDiagnosticListener class is applicable only for .NET 4.6, and not for .NET core.
13
// This HttpHandlerDiagnosticListener class is applicable only for .NET 4.6, and not for .NET core.
13

14

@@ -557,33 +558,69 @@ private HttpHandlerDiagnosticListener() : base(DiagnosticListenerName)
557

558

558
private void RaiseRequestEvent(HttpWebRequest request)
559
private void RaiseRequestEvent(HttpWebRequest request)
559
{
560
{
560-
// If System.Net.Http.Request is on, raise the event
561+
if (request.Headers.Get(RequestIdHeaderName) != null)
561-
if (this.IsEnabled(RequestWriteName))
562
{
562
{
563-
long timestamp = Stopwatch.GetTimestamp();
563+
// this request was instrumented by previous RaiseRequestEvent
564-
this.Write(RequestWriteName,
564+
return;
565-
new
565+
}
566+
567+
if (this.IsEnabled(ActivityName, request))
568+
{
569+
var activity = new Activity(ActivityName);
570+
571+
// Only send start event to users who subscribed for it, but start activity anyway
572+
if (this.IsEnabled(RequestStartName))
573+
{
574+
long timestamp = Stopwatch.GetTimestamp();
575+
this.StartActivity(activity,
576+
new
577+
{
578+
Request = request,
579+
Timestamp = timestamp
580+
});
581+
}
582+
else
583+
{
584+
activity.Start();
585+
}
586+
587+
request.Headers.Add(RequestIdHeaderName, activity.Id);
588+
//we expect baggage to be empty or contain a few items
589+
using (IEnumerator<KeyValuePair<string, string>> e = activity.Baggage.GetEnumerator())
590+
{
591+
if (e.MoveNext())
566
{
592
{
567-
Request = request,
593+
StringBuilder baggage = new StringBuilder();
568-
Timestamp = timestamp
594+
do
595+
{
596+
KeyValuePair<string, string> item = e.Current;
597+
baggage.Append(item.Key).Append('=').Append(item.Value).Append(',');
598+
}
599+
while (e.MoveNext());
600+
baggage.Remove(baggage.Length - 1, 1);
601+
request.Headers.Add(CorrelationContextHeaderName, baggage.ToString());
569
}
602
}
570-
);
603+
}
604+
605+
// There is no gurantee that Activity.Current will flow to the Response, so let's stop it here
606+
activity.Stop();
571
}
607
}
572
}
608
}
573

609

574
private void RaiseResponseEvent(HttpWebRequest request, HttpWebResponse response)
610
private void RaiseResponseEvent(HttpWebRequest request, HttpWebResponse response)
575
{
611
{
576-
if (this.IsEnabled(ResponseWriteName))
612+
// Response event could be received several times for the same request
613+
if (request.Headers[RequestIdHeaderName] != null)
577
{
614
{
615+
// only send Stop if request was instrumented
578
long timestamp = Stopwatch.GetTimestamp();
616
long timestamp = Stopwatch.GetTimestamp();
579-
this.Write(ResponseWriteName,
617+
this.Write(RequestStopName,
580
new
618
new
581
{
619
{
582
Request = request,
620
Request = request,
583
Response = response,
621
Response = response,
584
Timestamp = timestamp
622
Timestamp = timestamp
585-
}
623+
});
586-
);
587
}
624
}
588
}
625
}
589

626

@@ -647,9 +684,12 @@ private static void PerformInjection()
647

684

648
#region private fields
685
#region private fields
649
private const string DiagnosticListenerName = "System.Net.Http.Desktop";
686
private const string DiagnosticListenerName = "System.Net.Http.Desktop";
650-
private const string RequestWriteName = "System.Net.Http.Request";
687+
private const string ActivityName = "System.Net.Http.Desktop.HttpRequestOut";
651-
private const string ResponseWriteName = "System.Net.Http.Response";
688+
private const string RequestStartName = "System.Net.Http.Desktop.HttpRequestOut.Start";
689+
private const string RequestStopName = "System.Net.Http.Desktop.HttpRequestOut.Stop";
652
private const string InitializationFailed = "System.Net.Http.InitializationFailed";
690
private const string InitializationFailed = "System.Net.Http.InitializationFailed";
691+
private const string RequestIdHeaderName = "Request-Id";
692+
private const string CorrelationContextHeaderName = "Correlation-Context";
653

693

654
// Fields for controlling initialization of the HttpHandlerDiagnosticListener singleton
694
// Fields for controlling initialization of the HttpHandlerDiagnosticListener singleton
655
private bool initialized = false;
695
private bool initialized = false;

0 commit comments

Comments
 (0)