Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ internal enum UserAgentFeatureFlags
{
PerPartitionAutomaticFailover = 1,

PerPartitionCircuitBreaker = 2,
PerPartitionCircuitBreaker = 2,

ThinClient = 3,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ThinClient in diagnostic naming feels not right. At=least syntactically ThinProxy might be right mapping.
Might be even better to have an abstract notion (like GWV2 etc...) thoughts?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - ThinProxy sounds better.


BinaryEncoding = 4,
}
}
10 changes: 10 additions & 0 deletions Microsoft.Azure.Cosmos/src/DocumentClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6858,6 +6858,16 @@ internal string GetUserAgentFeatures()
featureFlag += (int)UserAgentFeatureFlags.PerPartitionCircuitBreaker;
}

if (this.isThinClientEnabled)
{
featureFlag += (int)UserAgentFeatureFlags.ThinClient;
}

if (ConfigurationManager.IsBinaryEncodingEnabled())
{
featureFlag += (int)UserAgentFeatureFlags.BinaryEncoding;
}

return featureFlag == 0 ? string.Empty : $"F{featureFlag:X}";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ internal sealed class ClientSideRequestStatisticsTraceDatum : TraceDatum, IClien
private readonly Dictionary<string, AddressResolutionStatistics> endpointToAddressResolutionStats;
private readonly List<StoreResponseStatistics> storeResponseStatistics;
private readonly List<HttpResponseStatistics> httpResponseStatistics;
private readonly List<HttpResponseStatistics> thinclientResponseStatistics;

private IReadOnlyDictionary<string, AddressResolutionStatistics> shallowCopyOfEndpointToAddressResolutionStatistics = null;
private IReadOnlyList<StoreResponseStatistics> shallowCopyOfStoreResponseStatistics = null;
private IReadOnlyList<HttpResponseStatistics> shallowCopyOfHttpResponseStatistics = null;
private IReadOnlyList<HttpResponseStatistics> shallowCopyOfHttpResponseStatistics = null;
private IReadOnlyList<HttpResponseStatistics> shallowCopyOfThinclientResponseStatistics = null;
private SystemUsageHistory systemUsageHistory = null;

public ClientSideRequestStatisticsTraceDatum(DateTime startTime, ITrace trace)
Expand All @@ -42,7 +44,8 @@ public ClientSideRequestStatisticsTraceDatum(DateTime startTime, ITrace trace)
this.storeResponseStatistics = new List<StoreResponseStatistics>();
this.FailedReplicas = new HashSet<TransportAddressUri>();
this.RegionsContacted = new HashSet<(string, Uri)>();
this.httpResponseStatistics = new List<HttpResponseStatistics>();
this.httpResponseStatistics = new List<HttpResponseStatistics>();
this.thinclientResponseStatistics = new List<HttpResponseStatistics>();
this.Trace = trace;
}

Expand Down Expand Up @@ -92,8 +95,8 @@ public IReadOnlyList<StoreResponseStatistics> StoreResponseStatisticsList
return this.shallowCopyOfStoreResponseStatistics;
}
}
}

}
public IReadOnlyList<HttpResponseStatistics> HttpResponseStatisticsList
{
get
Expand All @@ -109,6 +112,23 @@ public IReadOnlyList<HttpResponseStatistics> HttpResponseStatisticsList
return this.shallowCopyOfHttpResponseStatistics;
}
}
}

public IReadOnlyList<HttpResponseStatistics> ThinclientResponseStatisticsList
{
get
{
if (this.thinclientResponseStatistics.Count == 0)
{
return ClientSideRequestStatisticsTraceDatum.EmptyHttpResponseStatistics;
}

lock (this.thinclientResponseStatistics)
{
this.shallowCopyOfThinclientResponseStatistics ??= new List<HttpResponseStatistics>(this.thinclientResponseStatistics);
return this.shallowCopyOfThinclientResponseStatistics;
}
}
}

public TimeSpan? RequestLatency
Expand Down Expand Up @@ -345,7 +365,12 @@ public void RecordHttpResponse(HttpRequestMessage request,
HttpResponseMessage response,
ResourceType resourceType,
DateTime requestStartTimeUtc)
{
{
if (request.Version == new Version(2, 0))
{
this.RecordThinclientHttpResponse(request, response, resourceType, requestStartTimeUtc);
return;
}
DateTime requestEndTimeUtc = DateTime.UtcNow;
this.UpdateRequestEndTime(requestEndTimeUtc);

Expand Down Expand Up @@ -375,7 +400,12 @@ public void RecordHttpException(HttpRequestMessage request,
Exception exception,
ResourceType resourceType,
DateTime requestStartTimeUtc)
{
{
if (request.Version == new Version(2, 0))
{
this.RecordThinclientHttpException(request, exception, resourceType, requestStartTimeUtc);
return;
}
DateTime requestEndTimeUtc = DateTime.UtcNow;
this.UpdateRequestEndTime(requestEndTimeUtc);

Expand All @@ -400,6 +430,70 @@ public void RecordHttpException(HttpRequestMessage request,
exception: exception,
region: Convert.ToString(regionName)));
}
}

public void RecordThinclientHttpResponse(
HttpRequestMessage request,
HttpResponseMessage response,
ResourceType resourceType,
DateTime requestStartTimeUtc)
{
DateTime requestEndTimeUtc = DateTime.UtcNow;
this.UpdateRequestEndTime(requestEndTimeUtc);

lock (this.thinclientResponseStatistics)
{
Uri locationEndpoint = request.RequestUri;
object regionName = null;
if (request.Properties != null &&
request.Properties.TryGetValue(HttpRequestRegionNameProperty, out regionName))
{
this.TraceSummary?.AddRegionContacted(Convert.ToString(regionName), locationEndpoint);
}

this.shallowCopyOfThinclientResponseStatistics = null;
this.thinclientResponseStatistics.Add(new HttpResponseStatistics(
requestStartTimeUtc,
requestEndTimeUtc,
request.RequestUri,
request.Method,
resourceType,
response,
exception: null,
region: Convert.ToString(regionName)));
}
}

public void RecordThinclientHttpException(
HttpRequestMessage request,
Exception exception,
ResourceType resourceType,
DateTime requestStartTimeUtc)
{
DateTime requestEndTimeUtc = DateTime.UtcNow;
this.UpdateRequestEndTime(requestEndTimeUtc);

lock (this.thinclientResponseStatistics)
{
Uri locationEndpoint = request.RequestUri;
object regionName = null;
if (request.Properties != null &&
request.Properties.TryGetValue(HttpRequestRegionNameProperty, out regionName))
{
this.TraceSummary?.AddRegionContacted(Convert.ToString(regionName), locationEndpoint);
}

this.shallowCopyOfThinclientResponseStatistics = null;
this.thinclientResponseStatistics.Add(new HttpResponseStatistics(
requestStartTimeUtc,
requestEndTimeUtc,
request.RequestUri,
request.Method,
resourceType,
responseMessage: null,
exception: exception,
region: Convert.ToString(regionName)));
}
}

private DateTime UpdateRequestEndTime(DateTime requestEndTimeUtc)
Expand Down Expand Up @@ -533,6 +627,6 @@ public HttpResponseStatistics(
public Uri RequestUri { get; }
public string ActivityId { get; }
public long? ResponseContentLength { get; }
}
}
}
}
167 changes: 110 additions & 57 deletions Microsoft.Azure.Cosmos/src/Tracing/TraceData/SummaryDiagnostics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ public SummaryDiagnostics(ITrace trace)
this.DirectRequestsSummary
= new Lazy<Dictionary<(int, int), int>>(() => new Dictionary<(int, int), int>());
this.GatewayRequestsSummary
= new Lazy<Dictionary<(int, int), int>>(() => new Dictionary<(int, int), int>());
= new Lazy<Dictionary<(int, int), int>>(() => new Dictionary<(int, int), int>());
this.ThinclientRequestsSummary
= new Lazy<Dictionary<(int, int), int>>(() => new Dictionary<(int, int), int>());

this.AllRegionsContacted
= new Lazy<HashSet<Uri>>(() => new HashSet<Uri>());

Expand All @@ -31,27 +34,34 @@ public SummaryDiagnostics(ITrace trace)

public Lazy<List<StoreResponseStatistics>> StoreResponseStatistics { get; private set; } = new Lazy<List<StoreResponseStatistics>>(() => new List<StoreResponseStatistics>());
// Count of (StatusCode, SubStatusCode) tuples
public Lazy<Dictionary<(int statusCode, int subStatusCode), int>> DirectRequestsSummary { get; private set; }

public Lazy<Dictionary<(int statusCode, int subStatusCode), int>> DirectRequestsSummary { get; private set; }

public Lazy<List<HttpResponseStatistics>> ThinclientResponseStatistics { get; private set; } = new Lazy<List<HttpResponseStatistics>>(() => new List<HttpResponseStatistics>());
public Lazy<Dictionary<(int statusCode, int subStatusCode), int>> ThinclientRequestsSummary { get; private set; }
public Lazy<List<HttpResponseStatistics>> HttpResponseStatistics { get; private set; } = new Lazy<List<HttpResponseStatistics>>(() => new List<HttpResponseStatistics>());
public Lazy<Dictionary<(int statusCode, int subStatusCode), int>> GatewayRequestsSummary { get; private set; }

private void CollectSummaryFromTraceTree(ITrace currentTrace)
{
foreach (object datums in currentTrace.Data.Values)
{
if (datums is ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum)
{
this.AggregateStatsFromStoreResults(clientSideRequestStatisticsTraceDatum.StoreResponseStatisticsList);
this.AggregateGatewayStatistics(clientSideRequestStatisticsTraceDatum.HttpResponseStatisticsList);
this.AggregateRegionsContacted(clientSideRequestStatisticsTraceDatum.RegionsContacted);
}
}

foreach (ITrace childTrace in currentTrace.Children)
{
this.CollectSummaryFromTraceTree(childTrace);
}

private void CollectSummaryFromTraceTree(ITrace currentTrace)
{
foreach (object datums in currentTrace.Data.Values)
{
if (datums is ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum)
{
this.AggregateStatsFromStoreResults(clientSideRequestStatisticsTraceDatum.StoreResponseStatisticsList);
this.AggregateGatewayStatistics(clientSideRequestStatisticsTraceDatum.HttpResponseStatisticsList);
this.AggregateRegionsContacted(clientSideRequestStatisticsTraceDatum.RegionsContacted);

if (clientSideRequestStatisticsTraceDatum.ThinclientResponseStatisticsList != null)
{
this.AggregateThinclientStatistics(clientSideRequestStatisticsTraceDatum.ThinclientResponseStatisticsList);
}
}
}

foreach (ITrace childTrace in currentTrace.Children)
{
this.CollectSummaryFromTraceTree(childTrace);
}
}

private void AggregateRegionsContacted(HashSet<(string, Uri)> regionsContacted)
Expand Down Expand Up @@ -112,43 +122,86 @@ private void AggregateStatsFromStoreResults(IReadOnlyList<ClientSideRequestStati
this.DirectRequestsSummary.Value[(statusCode, subStatusCode)]++;
}
}
}

public void WriteSummaryDiagnostics(IJsonWriter jsonWriter)
{
jsonWriter.WriteObjectStart();

if (this.DirectRequestsSummary.IsValueCreated)
{
jsonWriter.WriteFieldName("DirectCalls");
jsonWriter.WriteObjectStart();
foreach (KeyValuePair<(int, int), int> kvp in this.DirectRequestsSummary.Value)
{
jsonWriter.WriteFieldName(kvp.Key.ToString());
jsonWriter.WriteNumberValue(kvp.Value);
}
jsonWriter.WriteObjectEnd();
}

if (this.AllRegionsContacted.IsValueCreated)
{
jsonWriter.WriteFieldName("RegionsContacted");
jsonWriter.WriteNumberValue(this.AllRegionsContacted.Value.Count);
}

if (this.GatewayRequestsSummary.IsValueCreated)
{
jsonWriter.WriteFieldName("GatewayCalls");
jsonWriter.WriteObjectStart();
foreach (KeyValuePair<(int, int), int> kvp in this.GatewayRequestsSummary.Value)
{
jsonWriter.WriteFieldName(kvp.Key.ToString());
jsonWriter.WriteNumberValue(kvp.Value);
}
jsonWriter.WriteObjectEnd();
}

jsonWriter.WriteObjectEnd();
}

private void AggregateThinclientStatistics(IReadOnlyList<ClientSideRequestStatisticsTraceDatum.HttpResponseStatistics> thinclientResponseStatisticsList)
{
foreach (ClientSideRequestStatisticsTraceDatum.HttpResponseStatistics thinclientResponseStatistics in thinclientResponseStatisticsList)
{
this.ThinclientResponseStatistics.Value.Add(thinclientResponseStatistics); // <-- Add this line

int statusCode = 0;
int substatusCode = 0;
if (thinclientResponseStatistics.HttpResponseMessage != null)
{
statusCode = (int)thinclientResponseStatistics.HttpResponseMessage.StatusCode;
if (!int.TryParse(SummaryDiagnostics.GetSubStatusCodes(thinclientResponseStatistics),
NumberStyles.Integer,
CultureInfo.InvariantCulture,
out substatusCode))
{
substatusCode = 0;
}
}

if (!this.ThinclientRequestsSummary.Value.ContainsKey((statusCode, substatusCode)))
{
this.ThinclientRequestsSummary.Value[(statusCode, substatusCode)] = 1;
}
else
{
this.ThinclientRequestsSummary.Value[(statusCode, substatusCode)]++;
}
}
}

public void WriteSummaryDiagnostics(IJsonWriter jsonWriter)
{
jsonWriter.WriteObjectStart();

if (this.DirectRequestsSummary.IsValueCreated)
{
jsonWriter.WriteFieldName("DirectCalls");
jsonWriter.WriteObjectStart();
foreach (KeyValuePair<(int, int), int> kvp in this.DirectRequestsSummary.Value)
{
jsonWriter.WriteFieldName(kvp.Key.ToString());
jsonWriter.WriteNumberValue(kvp.Value);
}
jsonWriter.WriteObjectEnd();
}

if (this.AllRegionsContacted.IsValueCreated)
{
jsonWriter.WriteFieldName("RegionsContacted");
jsonWriter.WriteNumberValue(this.AllRegionsContacted.Value.Count);
}

if (this.GatewayRequestsSummary.IsValueCreated)
{
jsonWriter.WriteFieldName("GatewayCalls");
jsonWriter.WriteObjectStart();
foreach (KeyValuePair<(int, int), int> kvp in this.GatewayRequestsSummary.Value)
{
jsonWriter.WriteFieldName(kvp.Key.ToString());
jsonWriter.WriteNumberValue(kvp.Value);
}
jsonWriter.WriteObjectEnd();
}

if (this.ThinclientRequestsSummary.IsValueCreated)
{
jsonWriter.WriteFieldName("ThinclientCalls");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change it to ProxyCalls ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep thinclient across, thinclient is the mode name and summary has details about different mode names.

jsonWriter.WriteObjectStart();
foreach (KeyValuePair<(int, int), int> kvp in this.ThinclientRequestsSummary.Value)
{
jsonWriter.WriteFieldName(kvp.Key.ToString());
jsonWriter.WriteNumberValue(kvp.Value);
}
jsonWriter.WriteObjectEnd();
}

jsonWriter.WriteObjectEnd();
}

/// <summary>
Expand Down
Loading
Loading