Skip to content

Commit

Permalink
Context propagation - OTEP-66 (#462)
Browse files Browse the repository at this point in the history
* consolidate all files under DistributeContext to Context in API and SDK

* rename DistributedContext classes to CorrelationContext et al

* update missed test renaming

* re-add DistributedContext and refactor carrier to use it

* add IEquatable to DistributedContext

* AspNet request collector (#543)

* Added a collector for incoming ASP.NET requests.

* Unit tests.

* Code review.

* Attempting to get windows build working.

* Attempting to fix build.

* Attempting to get the build working.

* Attempting to get the build working.

* Attempting to fix the build.

* Attempting to get Linux build working.

* Attempting to get linux build working.

* Attempting to get linux build working.

* Attempting to get build working.

* Attempting to get all tests running on windows.

* Attempting to get tests running on windows.

* Attempting to get the myget build working.

* Indention fix in myget yml.

* Code review.

* Code review.

* Code review.

* Code review.

* Code review.

* Fix build (#548)

* fix build

* rename queue to pool

* do not pack tests

* try to switch to VSBuild

* rename CorrelationContextScopeTest to DistributedContextScopeTest

* remove UpdateThreadArguments class from LastValueAggregatorTest (#552)

* Added support for .NET Framework HttpClient & HttpWebRequest dependency collection. (#553)

* Added support for .NET Framework HttpClient & HttpWebRequest dependency collection.

* Code review feedback.

* Updated HttpHandlerDiagnosticListener with latest changes from dotnet/runtime. Added try/finally for span.End calls. Fixed missing span.End in Sql exception event.

* Fixed broken SqlClientTests.

* A few tweaks to README for recent collector changes.

* Tested Azure SDK exception path and updated the TODO comment.

* Wrapping up enumerables for #407 and some cleanup (#558)

* Wrapping up enumerables for #407 and some cleanup

* Fixing whitespaces

* One more

Co-authored-by: Sergey Kanzhelev <S.Kanzhelev@live.com>

* fixes #559 (#563)

* Fixed the solution not building from dotnet build CLI. (#554)

Co-authored-by: Sergey Kanzhelev <S.Kanzhelev@live.com>

* Adding method to EvictingQueue, updating SpanSdk to update if key exists (#557)

* Adding method to EvictingQueue, updating SpanSdk to update if key exists

* Adding Replacing test to EvictingQueue; Updating SpanTest; Renaming from Update to Replace

* Adding wrapper to AddOrUpdateAttribute, adding validation to index in Replace method

* Adding NoReplacing Test when element doesn't exist

Co-authored-by: Sergey Kanzhelev <S.Kanzhelev@live.com>

* Attempting to fix the myget build pipeline so the packages come out valid on the other end. (#565)

I don't have a way to start a build from fork. So let's test right in master...

* updating README.md samples (#556)

* updating README.md samples

* adding missing variables to example

* updating samples in readme

Co-authored-by: Mike Goldsmith <goldsmith.mike@gmail.com>

* Implemented short-live bound instruments. (#547)

* Initial draft for implementing record cleanup. Implemented for longCounters only. One basic test as well.

* small fixes

* Test for double counter

* Double test counter

* Use instrument level lock

* Added comment.

* Tests fix

* minor

* Added new intermediate status NoPendingUpdate for instrument record. This greatly reduced the need to take locks

* comment

* Fixed CurrentBatches dictionary being modified while a flush is running. (#571)

Co-authored-by: Sergey Kanzhelev <S.Kanzhelev@live.com>

* Fixed up Jaeger project so that correct Thrift.dll is included in the nupkg & ApacheThrift is listed as a dependency. (#566)

Co-authored-by: Sergey Kanzhelev <S.Kanzhelev@live.com>

* ASP.NET dependency collector fixes and cleanup. (#570)

* Updated with latest bug fixes. Refactored to fit into OT solution.

* Ported bug fixes and unit tests.

* Code review.

* Unit test improvement.

* Code review.

* Fixed crashing TestServer on close.

Co-authored-by: Sergey Kanzhelev <S.Kanzhelev@live.com>

* add LS access token header to http request (#587)

* Clone Activity tags to Span Attributes (#572)

Resolves #430

* Initial work for validation

* Changed activity tags creation

Co-authored-by: Mike Goldsmith <goldsmith.mike@gmail.com>

* consolidate all files under DistributeContext to Context in API and SDK

* rename DistributedContext classes to CorrelationContext et al

* update missed test renaming

* re-add DistributedContext and refactor carrier to use it

* Fix build (#548)

* fix build

* rename queue to pool

* do not pack tests

* try to switch to VSBuild

* replace CorrelationContext with DistributedContext in BinarySerializer

* revert whitespace fixes to simplify review

* Update src/OpenTelemetry.Api/Context/CorrelationContext.cs

Co-Authored-By: Bruno Garcia <bruno@brunogarcia.com>

* Update src/OpenTelemetry.Api/Context/DistributedContextBuilder.cs

Co-Authored-By: Bruno Garcia <bruno@brunogarcia.com>

Co-authored-by: Mikel Blanchard <mblanchard@macrosssoftware.com>
Co-authored-by: Sergey Kanzhelev <S.Kanzhelev@live.com>
Co-authored-by: Alexey Zimarev <alex@zimarev.com>
Co-authored-by: Eddy Nakamura <eddynaka@gmail.com>
Co-authored-by: Eddy Nakamura <ednakamu@microsoft.com>
Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
Co-authored-by: Bruno Santos <brunomiguelas@gmail.com>
Co-authored-by: Bruno Garcia <bruno@brunogarcia.com>
  • Loading branch information
9 people authored Apr 14, 2020
1 parent b35311e commit bc684ff
Show file tree
Hide file tree
Showing 24 changed files with 463 additions and 305 deletions.
76 changes: 76 additions & 0 deletions src/OpenTelemetry.Api/Context/CorrelationContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// <copyright file="CorrelationContext.cs" company="OpenTelemetry Authors">
// Copyright 2018, 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;
using System.Collections.Generic;
using System.Linq;

namespace OpenTelemetry.Context
{
/// <summary>
/// Correlation context.
/// </summary>
public readonly struct CorrelationContext : IEquatable<CorrelationContext>
{
private static readonly List<CorrelationContextEntry> EmptyList = new List<CorrelationContextEntry>();
private readonly List<CorrelationContextEntry> entries;

/// <summary>
/// Initializes a new instance of the <see cref="CorrelationContext"/> struct.
/// </summary>
/// <param name="entries">Entries for correlation context.</param>
internal CorrelationContext(List<CorrelationContextEntry> entries)
{
this.entries = entries;
}

/// <summary>
/// Gets empty object of <see cref="CorrelationContext"/> struct.
/// </summary>
public static CorrelationContext Empty { get; } = new CorrelationContext(EmptyList);

/// <summary>
/// Gets all the <see cref="CorrelationContextEntry"/> in this <see cref="CorrelationContext"/>.
/// </summary>
public IEnumerable<CorrelationContextEntry> Entries => this.entries;

/// <summary>
/// Gets the <see cref="CorrelationContextEntry"/> with the specified name.
/// </summary>
/// <param name="key">Name of the <see cref="CorrelationContextEntry"/> to get.</param>
/// <returns>The <see cref="string"/> with the specified name. If not found - null.</returns>
public string GetEntryValue(string key) => this.entries.LastOrDefault(x => x.Key == key).Value;

/// <inheritdoc/>
public bool Equals(CorrelationContext other)
{
if (this.entries.Count() != other.entries.Count())
{
return false;
}

foreach (CorrelationContextEntry entry in this.entries)
{
if (other.GetEntryValue(entry.Key) != entry.Value)
{
return false;
}
}

return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <copyright file="DistributedContextBuilder.cs" company="OpenTelemetry Authors">
// <copyright file="CorrelationContextBuilder.cs" company="OpenTelemetry Authors">
// Copyright 2018, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -19,17 +19,17 @@
namespace OpenTelemetry.Context
{
/// <summary>
/// Distributed context Builder.
/// Correlation context Builder.
/// </summary>
public struct DistributedContextBuilder
public struct CorrelationContextBuilder
{
private List<DistributedContextEntry> entries;
private List<CorrelationContextEntry> entries;

/// <summary>
/// Initializes a new instance of the <see cref="DistributedContextBuilder"/> struct.
/// Initializes a new instance of the <see cref="CorrelationContextBuilder"/> struct.
/// </summary>
/// <param name="inheritCurrentContext">Flag to allow inheriting the current context entries.</param>
public DistributedContextBuilder(bool inheritCurrentContext)
public CorrelationContextBuilder(bool inheritCurrentContext)
{
this.entries = null;

Expand All @@ -40,56 +40,56 @@ public DistributedContextBuilder(bool inheritCurrentContext)

if (inheritCurrentContext)
{
this.entries = new List<DistributedContextEntry>(DistributedContext.Current.Entries);
this.entries = new List<CorrelationContextEntry>(DistributedContext.Current.CorrelationContext.Entries);
}
}

/// <summary>
/// Initializes a new instance of the <see cref="DistributedContextBuilder"/> struct using some context.
/// Initializes a new instance of the <see cref="CorrelationContextBuilder"/> struct using some context.
/// </summary>
/// <param name="context">Initial context.</param>
public DistributedContextBuilder(DistributedContext context)
public CorrelationContextBuilder(CorrelationContext context)
{
if (DistributedContext.Carrier is NoopDistributedContextCarrier)
{
this.entries = null;
return;
}

this.entries = new List<DistributedContextEntry>(context.Entries);
this.entries = new List<CorrelationContextEntry>(context.Entries);
}

/// <summary>
/// Create <see cref="DistributedContext"/> instance from key and value entry.
/// Create <see cref="CorrelationContext"/> instance from key and value entry.
/// </summary>
/// <param name="key">Entry key.</param>
/// <param name="value">Entry value.</param>
/// <returns>Instance of <see cref="DistributedContext"/>.</returns>
public static DistributedContext CreateContext(string key, string value) =>
new DistributedContextBuilder(inheritCurrentContext: false).Add(key, value).Build();
/// <returns>Instance of <see cref="CorrelationContext"/>.</returns>
public static CorrelationContext CreateContext(string key, string value) =>
new CorrelationContextBuilder(inheritCurrentContext: false).Add(key, value).Build();

/// <summary>
/// Create <see cref="DistributedContext"/> instance from entry.
/// Create <see cref="CorrelationContext"/> instance from entry.
/// </summary>
/// <param name="entry">Entry to add to the context.</param>
/// <returns>Instance of <see cref="DistributedContext"/>.</returns>
public static DistributedContext CreateContext(DistributedContextEntry entry) =>
new DistributedContextBuilder(inheritCurrentContext: false).Add(entry).Build();
/// <returns>Instance of <see cref="CorrelationContext"/>.</returns>
public static CorrelationContext CreateContext(CorrelationContextEntry entry) =>
new CorrelationContextBuilder(inheritCurrentContext: false).Add(entry).Build();

/// <summary>
/// Create <see cref="DistributedContext"/> instance from entry.
/// Create <see cref="CorrelationContext"/> instance from entry.
/// </summary>
/// <param name="entries">List of entries to add to the context.</param>
/// <returns>Instance of <see cref="DistributedContext"/>.</returns>
public static DistributedContext CreateContext(IEnumerable<DistributedContextEntry> entries) =>
new DistributedContextBuilder(inheritCurrentContext: false).Add(entries).Build();
/// <returns>Instance of <see cref="CorrelationContext"/>.</returns>
public static CorrelationContext CreateContext(IEnumerable<CorrelationContextEntry> entries) =>
new CorrelationContextBuilder(inheritCurrentContext: false).Add(entries).Build();

/// <summary>
/// Add Distributed Context entry to the builder.
/// </summary>
/// <param name="entry">Entry to add to the context.</param>
/// <returns>The current <see cref="DistributedContextBuilder"/> instance.</returns>
public DistributedContextBuilder Add(DistributedContextEntry entry)
/// <returns>The current <see cref="CorrelationContextBuilder"/> instance.</returns>
public CorrelationContextBuilder Add(CorrelationContextEntry entry)
{
if (DistributedContext.Carrier is NoopDistributedContextCarrier || entry == default)
{
Expand All @@ -98,7 +98,7 @@ public DistributedContextBuilder Add(DistributedContextEntry entry)

if (this.entries == null)
{
this.entries = new List<DistributedContextEntry>();
this.entries = new List<CorrelationContextEntry>();
}
else
{
Expand All @@ -122,29 +122,29 @@ public DistributedContextBuilder Add(DistributedContextEntry entry)
/// <param name="key">Entry key.</param>
/// <param name="value">Entry value.</param>
/// <param name="metadata">Entry metadata.</param>
/// <returns>The current <see cref="DistributedContextBuilder"/> instance.</returns>
public DistributedContextBuilder Add(string key, string value, EntryMetadata metadata)
/// <returns>The current <see cref="CorrelationContextBuilder"/> instance.</returns>
public CorrelationContextBuilder Add(string key, string value, EntryMetadata metadata)
{
return this.Add(new DistributedContextEntry(key, value, metadata));
return this.Add(new CorrelationContextEntry(key, value, metadata));
}

/// <summary>
/// Add Distributed Context entry to the builder.
/// </summary>
/// <param name="key">Entry key.</param>
/// <param name="value">Entry value.</param>
/// <returns>The current <see cref="DistributedContextBuilder"/> instance.</returns>
public DistributedContextBuilder Add(string key, string value)
/// <returns>The current <see cref="CorrelationContextBuilder"/> instance.</returns>
public CorrelationContextBuilder Add(string key, string value)
{
return this.Add(new DistributedContextEntry(key, value));
return this.Add(new CorrelationContextEntry(key, value));
}

/// <summary>
/// Add Distributed Context entry to the builder.
/// </summary>
/// <param name="entries">List of entries to add to the context.</param>
/// <returns>The current <see cref="DistributedContextBuilder"/> instance.</returns>
public DistributedContextBuilder Add(IEnumerable<DistributedContextEntry> entries)
/// <returns>The current <see cref="CorrelationContextBuilder"/> instance.</returns>
public CorrelationContextBuilder Add(IEnumerable<CorrelationContextEntry> entries)
{
if (DistributedContext.Carrier is NoopDistributedContextCarrier || entries == null)
{
Expand All @@ -163,8 +163,8 @@ public DistributedContextBuilder Add(IEnumerable<DistributedContextEntry> entrie
/// Remove Distributed Context entry from the context.
/// </summary>
/// <param name="key">Entry key.</param>
/// <returns>The current <see cref="DistributedContextBuilder"/> instance.</returns>
public DistributedContextBuilder Remove(string key)
/// <returns>The current <see cref="CorrelationContextBuilder"/> instance.</returns>
public CorrelationContextBuilder Remove(string key)
{
if (key == null || DistributedContext.Carrier is NoopDistributedContextCarrier || this.entries == null)
{
Expand All @@ -181,17 +181,17 @@ public DistributedContextBuilder Remove(string key)
}

/// <summary>
/// Build a Distributed Context from current builder.
/// Build a Correlation Context from current builder.
/// </summary>
/// <returns><see cref="DistributedContext"/> instance.</returns>
public DistributedContext Build()
/// <returns><see cref="CorrelationContext"/> instance.</returns>
public CorrelationContext Build()
{
if (DistributedContext.Carrier is NoopDistributedContextCarrier || this.entries == null)
{
return DistributedContext.Empty;
return CorrelationContext.Empty;
}

var context = new DistributedContext(this.entries);
var context = new CorrelationContext(this.entries);
this.entries = null; // empty current builder entries.
return context;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <copyright file="DistributedContextEntry.cs" company="OpenTelemetry Authors">
// <copyright file="CorrelationContextEntry.cs" company="OpenTelemetry Authors">
// Copyright 2018, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -21,30 +21,30 @@ namespace OpenTelemetry.Context
/// <summary>
/// Distributed Context entry with the key, value and metadata.
/// </summary>
public readonly struct DistributedContextEntry
public readonly struct CorrelationContextEntry
{
/// <summary>
/// Initializes a new instance of the <see cref="DistributedContextEntry"/> struct with the key and value.
/// Initializes a new instance of the <see cref="CorrelationContextEntry"/> struct with the key and value.
/// </summary>
/// <param name="key">Key name for the entry.</param>
/// <param name="value">Value associated with the key name.</param>
public DistributedContextEntry(string key, string value)
public CorrelationContextEntry(string key, string value)
: this(key, value, EntryMetadata.NoPropagationEntry)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="DistributedContextEntry"/> struct with the key, value, and metadata.
/// Initializes a new instance of the <see cref="CorrelationContextEntry"/> struct with the key, value, and metadata.
/// </summary>
/// <param name="key">Key name for the entry.</param>
/// <param name="value">Value associated with the key name.</param>
/// <param name="metadata">Entry metadata.</param>
public DistributedContextEntry(string key, string value, in EntryMetadata metadata)
public CorrelationContextEntry(string key, string value, in EntryMetadata metadata)
{
if (key == null)
{
this.Key = string.Empty;
OpenTelemetryApiEventSource.Log.InvalidArgument(nameof(DistributedContextEntry), nameof(key), "is null");
OpenTelemetryApiEventSource.Log.InvalidArgument(nameof(CorrelationContextEntry), nameof(key), "is null");
}
else
{
Expand All @@ -54,7 +54,7 @@ public DistributedContextEntry(string key, string value, in EntryMetadata metada
if (value == null)
{
this.Value = string.Empty;
OpenTelemetryApiEventSource.Log.InvalidArgument(nameof(DistributedContextEntry), nameof(value), "is null");
OpenTelemetryApiEventSource.Log.InvalidArgument(nameof(CorrelationContextEntry), nameof(value), "is null");
}
else
{
Expand All @@ -80,29 +80,29 @@ public DistributedContextEntry(string key, string value, in EntryMetadata metada
public EntryMetadata Metadata { get; }

/// <summary>
/// Compare two entries of <see cref="DistributedContextEntry"/> for equality.
/// Compare two entries of <see cref="CorrelationContextEntry"/> for equality.
/// </summary>
/// <param name="entry1">First Entry to compare.</param>
/// <param name="entry2">Second Entry to compare.</param>
public static bool operator ==(DistributedContextEntry entry1, DistributedContextEntry entry2) => entry1.Equals(entry2);
public static bool operator ==(CorrelationContextEntry entry1, CorrelationContextEntry entry2) => entry1.Equals(entry2);

/// <summary>
/// Compare two entries of <see cref="DistributedContextEntry"/> for not equality.
/// Compare two entries of <see cref="CorrelationContextEntry"/> for not equality.
/// </summary>
/// <param name="entry1">First Entry to compare.</param>
/// <param name="entry2">Second Entry to compare.</param>
public static bool operator !=(DistributedContextEntry entry1, DistributedContextEntry entry2) => !entry1.Equals(entry2);
public static bool operator !=(CorrelationContextEntry entry1, CorrelationContextEntry entry2) => !entry1.Equals(entry2);

/// <inheritdoc/>
public override bool Equals(object o)
{
return o is DistributedContextEntry that && (this.Key == that.Key && this.Value == that.Value);
return o is CorrelationContextEntry that && (this.Key == that.Key && this.Value == that.Value);
}

/// <inheritdoc/>
public override string ToString()
{
return this.Key is null ? "{}" : $"{nameof(DistributedContextEntry)}{{{nameof(this.Key)}={this.Key}, {nameof(this.Value)}={this.Value}}}";
return this.Key is null ? "{}" : $"{nameof(CorrelationContextEntry)}{{{nameof(this.Key)}={this.Key}, {nameof(this.Value)}={this.Value}}}";
}

/// <inheritdoc/>
Expand Down
Loading

0 comments on commit bc684ff

Please sign in to comment.