Skip to content

Commit

Permalink
Internal Tracing : Adds tracing library to the SDK (#1841)
Browse files Browse the repository at this point in the history
* drafted out trace library

* added no op trace

* got trace writer working

* made tracewriter static

* refactored out repeat code

* made character set configurable

* resolved iteration comments

* added support for multiple serialization formats

* fixed NRE do to stack frame not having file path

* removed unnecessary using
  • Loading branch information
bchong95 authored Sep 11, 2020
1 parent d48fb27 commit ed0c8f0
Show file tree
Hide file tree
Showing 18 changed files with 1,537 additions and 153 deletions.
3 changes: 1 addition & 2 deletions Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ public static SqlQuerySpec Evaluate(

public static bool IsTransformExpression(Expression expression)
{
MethodCallExpression methodCallExpression = expression as MethodCallExpression;
return methodCallExpression != null &&
return expression is MethodCallExpression methodCallExpression &&
methodCallExpression.Method.DeclaringType == typeof(DocumentQueryable) &&
(methodCallExpression.Method.Name == DocumentQueryEvaluator.SQLMethod);
}
Expand Down
294 changes: 153 additions & 141 deletions Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsTextWriter.cs

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ public void WriteQueryMetrics(QueryMetrics queryMetrics)
this.WriteRuntimesExecutionTimes(queryMetrics.BackendMetrics.RuntimeExecutionTimes);

this.WriteDocumentWriteTime(queryMetrics.BackendMetrics.DocumentWriteTime);

#if false
// ClientSideMetrics
this.WriteClientSideMetrics(queryMetrics.ClientSideMetrics);

// IndexUtilizationInfo
this.WriteBeforeIndexUtilizationInfo();

this.WriteIndexUtilizationInfo(queryMetrics.IndexUtilizationInfo);

#endif
this.WriteAfterQueryMetrics();
}

Expand All @@ -68,7 +68,7 @@ public void WriteQueryMetrics(QueryMetrics queryMetrics)

protected abstract void WriteTotalQueryExecutionTime(TimeSpan totalQueryExecutionTime);

#region QueryPreparationTimes
#region QueryPreparationTimes
private void WriteQueryPreparationTimes(QueryPreparationTimes queryPreparationTimes)
{
this.WriteBeforeQueryPreparationTimes();
Expand All @@ -92,15 +92,15 @@ private void WriteQueryPreparationTimes(QueryPreparationTimes queryPreparationTi
protected abstract void WriteQueryOptimizationTime(TimeSpan queryOptimizationTime);

protected abstract void WriteAfterQueryPreparationTimes();
#endregion
#endregion

protected abstract void WriteIndexLookupTime(TimeSpan indexLookupTime);

protected abstract void WriteDocumentLoadTime(TimeSpan documentLoadTime);

protected abstract void WriteVMExecutionTime(TimeSpan vMExecutionTime);

#region RuntimeExecutionTimes
#region RuntimeExecutionTimes
private void WriteRuntimesExecutionTimes(RuntimeExecutionTimes runtimeExecutionTimes)
{
this.WriteBeforeRuntimeExecutionTimes();
Expand All @@ -121,11 +121,11 @@ private void WriteRuntimesExecutionTimes(RuntimeExecutionTimes runtimeExecutionT
protected abstract void WriteUserDefinedFunctionExecutionTime(TimeSpan userDefinedFunctionExecutionTime);

protected abstract void WriteAfterRuntimeExecutionTimes();
#endregion
#endregion

protected abstract void WriteDocumentWriteTime(TimeSpan documentWriteTime);

#region ClientSideMetrics
#region ClientSideMetrics
private void WriteClientSideMetrics(ClientSideMetrics clientSideMetrics)
{
this.WriteBeforeClientSideMetrics();
Expand Down Expand Up @@ -224,16 +224,16 @@ private void WritePartitionSchedulingTimeSpan(string partitionId, SchedulingTime
protected abstract void WriteAfterSchedulingMetrics();

protected abstract void WriteAfterClientSideMetrics();
#endregion
#endregion

#region IndexUtilizationInfo
#region IndexUtilizationInfo

protected abstract void WriteBeforeIndexUtilizationInfo();

protected abstract void WriteIndexUtilizationInfo(IndexUtilizationInfo indexUtilizationInfo);

protected abstract void WriteAfterIndexUtilizationInfo();
#endregion
#endregion

protected abstract void WriteAfterQueryMetrics();
}
Expand Down
22 changes: 22 additions & 0 deletions Microsoft.Azure.Cosmos/src/Tracing/CallerInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Tracing
{
using System;

internal readonly struct CallerInfo
{
public CallerInfo(string memberName, string filePath, int lineNumber)
{
this.MemberName = memberName ?? throw new ArgumentNullException(nameof(memberName));
this.FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath));
this.LineNumber = lineNumber < 0 ? throw new ArgumentOutOfRangeException(nameof(lineNumber)) : lineNumber;
}

public string MemberName { get; }
public string FilePath { get; }
public int LineNumber { get; }
}
}
51 changes: 51 additions & 0 deletions Microsoft.Azure.Cosmos/src/Tracing/ITrace.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Tracing
{
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

internal interface ITrace : IDisposable
{
string Name { get; }

Guid Id { get; }

CallerInfo CallerInfo { get; }

DateTime StartTime { get; }

TimeSpan Duration { get; }

TraceLevel Level { get; }

TraceComponent Component { get; }

ITrace Parent { get; }

IReadOnlyList<ITrace> Children { get; }

IReadOnlyDictionary<string, object> Data { get; }

ITrace StartChild(
string name,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0);

ITrace StartChild(
string name,
TraceComponent component,
TraceLevel level,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0);

void AddDatum(string key, ITraceDatum traceDatum);

void AddDatum(string key, object value);
}
}
11 changes: 11 additions & 0 deletions Microsoft.Azure.Cosmos/src/Tracing/ITraceDatum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Tracing
{
internal interface ITraceDatum
{
void Accept(ITraceDatumVisitor traceDatumVisitor);
}
}
15 changes: 15 additions & 0 deletions Microsoft.Azure.Cosmos/src/Tracing/ITraceDatumVisitor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Tracing
{
using Microsoft.Azure.Cosmos.Tracing.TraceData;

internal interface ITraceDatumVisitor
{
void Visit(CosmosDiagnosticsTraceDatum cosmosDiagnosticsTraceDatum);

void Visit(QueryMetricsTraceDatum queryMetricsTraceDatum);
}
}
78 changes: 78 additions & 0 deletions Microsoft.Azure.Cosmos/src/Tracing/NoOpTrace.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Tracing
{
using System;
using System.Collections.Generic;
using System.Diagnostics;

internal sealed class NoOpTrace : ITrace
{
public static readonly NoOpTrace Singleton = new NoOpTrace();

private static readonly IReadOnlyList<ITrace> NoOpChildren = new List<ITrace>();
private static readonly IReadOnlyDictionary<string, object> NoOpData = new Dictionary<string, object>();
private static readonly CallerInfo NoOpCallerInfo = new CallerInfo(memberName: "NoOp", filePath: "NoOp", lineNumber: 9001);

private NoOpTrace()
{
}

public string Name => "NoOp";

public Guid Id => default;

public CallerInfo CallerInfo => NoOpCallerInfo;

public DateTime StartTime => default;

public TimeSpan Duration => default;

public TraceLevel Level => default;

public TraceComponent Component => default;

public ITrace Parent => null;

public IReadOnlyList<ITrace> Children => NoOpChildren;

public IReadOnlyDictionary<string, object> Data => NoOpData;

public void Dispose()
{
// NoOp
}

public ITrace StartChild(
string name,
string memberName = "",
string sourceFilePath = "",
int sourceLineNumber = 0) => this.StartChild(
name,
component: this.Component,
level: TraceLevel.Info);

public ITrace StartChild(
string name,
TraceComponent component,
TraceLevel level,
string memberName = "",
string sourceFilePath = "",
int sourceLineNumber = 0)
{
return this;
}

public void AddDatum(string key, ITraceDatum traceDatum)
{
// NoOp
}

public void AddDatum(string key, object value)
{
// NoOp
}
}
}
114 changes: 114 additions & 0 deletions Microsoft.Azure.Cosmos/src/Tracing/Trace.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Tracing
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;

internal sealed class Trace : ITrace
{
private readonly List<Trace> children;
private readonly Dictionary<string, object> data;
private readonly Stopwatch stopwatch;

private Trace(
string name,
CallerInfo callerInfo,
TraceLevel level,
TraceComponent component,
Trace parent)
{
this.Name = name ?? throw new ArgumentNullException(nameof(name));
this.Id = Guid.NewGuid();
this.CallerInfo = callerInfo;
this.StartTime = DateTime.UtcNow;
this.stopwatch = Stopwatch.StartNew();
this.Level = level;
this.Component = component;
this.Parent = parent;
this.children = new List<Trace>();
this.data = new Dictionary<string, object>();
}

public string Name { get; }

public Guid Id { get; }

public CallerInfo CallerInfo { get; }

public DateTime StartTime { get; }

public TimeSpan Duration => this.stopwatch.Elapsed;

public TraceLevel Level { get; }

public TraceComponent Component { get; }

public ITrace Parent { get; }

public IReadOnlyList<ITrace> Children => this.children;

public IReadOnlyDictionary<string, object> Data => this.data;

public void Dispose()
{
this.stopwatch.Stop();
}

public ITrace StartChild(
string name,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0) => this.StartChild(
name,
level: TraceLevel.Verbose,
component: this.Component,
memberName: memberName,
sourceFilePath: sourceFilePath,
sourceLineNumber: sourceLineNumber);

public ITrace StartChild(
string name,
TraceComponent component,
TraceLevel level,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
Trace child = new Trace(
name: name,
callerInfo: new CallerInfo(memberName, sourceFilePath, sourceLineNumber),
level: level,
component: component,
parent: this);
this.children.Add(child);
return child;
}

public static Trace GetRootTrace(string name) => Trace.GetRootTrace(
name,
component: TraceComponent.Unknown,
level: TraceLevel.Verbose);

public static Trace GetRootTrace(
string name,
TraceComponent component,
TraceLevel level,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0) => new Trace(
name: name,
callerInfo: new CallerInfo(memberName, sourceFilePath, sourceLineNumber),
level: level,
component: component,
parent: null);

public void AddDatum(string key, ITraceDatum traceDatum) => this.data.Add(key, traceDatum);

public void AddDatum(string key, object value) => this.data.Add(key, value);
}
}
13 changes: 13 additions & 0 deletions Microsoft.Azure.Cosmos/src/Tracing/TraceComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Tracing
{
internal enum TraceComponent
{
Transport,
Query,
Unknown,
}
}
Loading

0 comments on commit ed0c8f0

Please sign in to comment.