-
Notifications
You must be signed in to change notification settings - Fork 755
/
HttpClientLatencyLogEnricher.cs
84 lines (70 loc) · 2.98 KB
/
HttpClientLatencyLogEnricher.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Microsoft.Extensions.Diagnostics.Enrichment;
using Microsoft.Extensions.Diagnostics.Latency;
using Microsoft.Extensions.Http.Diagnostics;
using Microsoft.Extensions.Http.Logging;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Shared.Pools;
namespace Microsoft.Extensions.Http.Latency.Internal;
/// <summary>
/// The enricher appends checkpoints for the outgoing http request.
/// It also logs the server name from the response header to correlate logs between client and server.
/// </summary>
internal sealed class HttpClientLatencyLogEnricher : IHttpClientLogEnricher
{
private static readonly ObjectPool<StringBuilder> _builderPool = PoolFactory.SharedStringBuilderPool;
private readonly HttpClientLatencyContext _latencyContext;
private readonly CheckpointToken _enricherInvoked;
public HttpClientLatencyLogEnricher(HttpClientLatencyContext latencyContext, ILatencyContextTokenIssuer tokenIssuer)
{
_latencyContext = latencyContext;
_enricherInvoked = tokenIssuer.GetCheckpointToken(HttpCheckpoints.EnricherInvoked);
}
public void Enrich(IEnrichmentTagCollector collector, HttpRequestMessage request, HttpResponseMessage? response, Exception? exception)
{
if (response != null)
{
var lc = _latencyContext.Get();
lc?.AddCheckpoint(_enricherInvoked);
StringBuilder stringBuilder = _builderPool.Get();
// Add serverName, checkpoints to outgoing http logs.
AppendServerName(response.Headers, stringBuilder);
_ = stringBuilder.Append(',');
if (lc != null)
{
AppendCheckpoints(lc, stringBuilder);
}
collector.Add("LatencyInfo", stringBuilder.ToString());
_builderPool.Return(stringBuilder);
}
}
private static void AppendServerName(HttpHeaders headers, StringBuilder stringBuilder)
{
if (headers.TryGetValues(TelemetryConstants.ServerApplicationNameHeader, out var values))
{
_ = stringBuilder.Append(values!.First());
}
}
private static void AppendCheckpoints(ILatencyContext latencyContext, StringBuilder stringBuilder)
{
var latencyData = latencyContext.LatencyData;
for (int i = 0; i < latencyData.Checkpoints.Length; i++)
{
_ = stringBuilder.Append(latencyData.Checkpoints[i].Name);
_ = stringBuilder.Append('/');
}
_ = stringBuilder.Append(',');
for (int i = 0; i < latencyData.Checkpoints.Length; i++)
{
var ms = ((double)latencyData.Checkpoints[i].Elapsed / latencyData.Checkpoints[i].Frequency) * 1000;
_ = stringBuilder.Append(ms);
_ = stringBuilder.Append('/');
}
}
}