Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add guid correlation support and change activity processing #169

Merged
merged 14 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from 11 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
1 change: 1 addition & 0 deletions Dependencies.props
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<Microsoft_Extensions_Logging_Version>3.1.2</Microsoft_Extensions_Logging_Version>
<Microsoft_Extensions_DependencyInjection_Version>3.1.2</Microsoft_Extensions_DependencyInjection_Version>
<Microsoft_Extensions_Options_Version>3.1.2</Microsoft_Extensions_Options_Version>
<System_Threading_Tasks_Extensions_Version>4.5.3</System_Threading_Tasks_Extensions_Version>
<System_Diagnostics_DiagnosticSource_Version>4.7.0</System_Diagnostics_DiagnosticSource_Version>
<MSTest_TestFramework_Version>2.1.0</MSTest_TestFramework_Version>
<MSTest_TestAdapter_Version>2.1.0</MSTest_TestAdapter_Version>
Expand Down
93 changes: 93 additions & 0 deletions src/Extensions/Abstractions/Activities/ActivityExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;
using System.Diagnostics;

namespace Microsoft.Omex.Extensions.Abstractions.Activities
{
/// <summary>
/// Extensions for Activity
/// </summary>
public static class ActivityExtensions
{
/// <summary>
/// Get user hash from activity
/// </summary>
public static string GetUserHash(this Activity activity) =>
activity.GetBaggageItem(UserHashKey) ?? string.Empty;


/// <summary>
/// Returns true if activity is transaction
/// </summary>
public static bool IsTransaction(this Activity activity) =>
string.Equals(
activity.GetBaggageItem(TransactionMarkerKey),
TransactionMarkerValue,
StringComparison.OrdinalIgnoreCase);


/// <summary>
/// Set user hash for the activity
/// </summary>
/// <remarks>This property would be transfered to child activity and via web requests</remarks>
public static Activity SetUserHash(this Activity activity, string userHash) =>
activity.AddBaggage(UserHashKey, userHash);


/// <summary>
/// Mark activity as transaction
/// </summary>
/// <remarks>This property would be transfered to child activity and via web requests</remarks>
public static Activity MarkAsTransaction(this Activity activity) =>
activity.AddBaggage(TransactionMarkerKey, TransactionMarkerValue);


/// <summary>
/// Get correlation guid that is used by old Omex services
/// </summary>
[Obsolete(CorrelationIdObsoleteMessage, false)]
public static Guid? GetObsoleteCorrelationId(this Activity activity) =>
Guid.TryParse(activity.GetBaggageItem(ObsoleteCorrelationId), out Guid correlation)
AndreyTretyak marked this conversation as resolved.
Show resolved Hide resolved
? correlation
: (Guid?)null;


/// <summary>
/// Set correlation guid that is used by old Omex services
/// </summary>
/// <remarks>This property would be transfered to child activity and via web requests</remarks>
[Obsolete(CorrelationIdObsoleteMessage, false)]
public static Activity SetObsoleteCorrelationId(this Activity activity, Guid correlation) =>
activity.AddBaggage(ObsoleteCorrelationId, correlation.ToString());


/// <summary>
/// Get transaction id that is used by old Omex services
/// </summary>
[Obsolete(TransactionIdObsoleteMessage, false)]
public static uint? GetObsolteteTransactionId(this Activity activity) =>
uint.TryParse(activity.GetBaggageItem(ObsoleteTransactionId), out uint transactionId)
AndreyTretyak marked this conversation as resolved.
Show resolved Hide resolved
? transactionId
: (uint?)null;


/// <summary>
/// Set transaction id that is used by old Omex services
/// </summary>
/// <remarks>This property would be transfered to child activity and via web requests</remarks>
[Obsolete(TransactionIdObsoleteMessage, false)]
public static Activity SetObsoleteTransactionId(this Activity activity, uint transactionId) =>
activity.AddBaggage(ObsoleteTransactionId, transactionId.ToString());
Copy link
Member

@muiriswoulfe muiriswoulfe Mar 18, 2020

Choose a reason for hiding this comment

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

ToString [](start = 60, length = 8)

Add CultureInfo.InvariantCulture as a parameter to avoid differences in behaviour on different machines #Closed

Copy link
Contributor Author

@AndreyTretyak AndreyTretyak Mar 19, 2020

Choose a reason for hiding this comment

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

Fixed. Out of curiosity does it actually does anything for int? I'm not aware of different formats for it. #Closed

Copy link
Member

Choose a reason for hiding this comment

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

There are differing number systems around the world, which this could potentially get converted into. See https://en.wikipedia.org/wiki/Numeral_system#/media/File:Numeral_Systems_of_the_World.svg


In reply to: 394708563 [](ancestors = 394708563)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, I was hoping we have a single standard at least in numbers :) thanks



private const string UserHashKey = "UserHash";
private const string TransactionMarkerKey = "TransactionMarkerKey";
private const string TransactionMarkerValue = "true";
private const string ObsoleteCorrelationId = "ObsoleteCorrelationId";
private const string ObsoleteTransactionId = "ObsoleteTransactionId";
private const string CorrelationIdObsoleteMessage = "Please use Activity.Id for new services instead";
private const string TransactionIdObsoleteMessage = "Please use Activity.TraceId for new services instead";
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using Microsoft.Omex.Extensions.Abstractions;

namespace Microsoft.Omex.Extensions.TimedScopes
namespace Microsoft.Omex.Extensions.Abstractions.Activities
{
/// <summary>
/// Interface to create TimedScope
Expand All @@ -13,12 +11,12 @@ public interface ITimedScopeProvider
/// <summary>
/// Creates and start TimedScope
/// </summary>
TimedScope CreateAndStart(TimedScopeDefinition name, TimedScopeResult result);
TimedScope CreateAndStart(TimedScopeDefinition name, TimedScopeResult result = TimedScopeResult.SystemError);


/// <summary>
/// Creates TimedScope
/// </summary>
TimedScope Create(TimedScopeDefinition name, TimedScopeResult result);
TimedScope Create(TimedScopeDefinition name, TimedScopeResult result = TimedScopeResult.SystemError);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;

namespace Microsoft.Omex.Extensions.Abstractions.Activities.Processing
{
/// <summary>
/// Class with activity result enum string values to avoid alocations
/// </summary>
public static class ActivityResultStrings
{
/// <summary>
/// Activity SystemError result string
/// </summary>
public static string SystemError { get; } = "SystemError";


/// <summary>
/// Activity ExpectedError result string
/// </summary>
public static string ExpectedError { get; } = "ExpectedError";


/// <summary>
/// Activity Success result string
/// </summary>
public static string Success { get; } = "Success";


/// <summary>
/// Activity Unknown result string
/// </summary>
public static string Unknown { get; } = "Unknown";


/// <summary>
/// Returns corresponding to enum string value with creating new string
/// </summary>
public static string ResultToString(TimedScopeResult result) =>
result switch
{
TimedScopeResult.SystemError => SystemError,
TimedScopeResult.ExpectedError => ExpectedError,
TimedScopeResult.Success => Success,
#pragma warning disable CS0618 // need to handle all enum values
AndreyTretyak marked this conversation as resolved.
Show resolved Hide resolved
TimedScopeResult.Unknown => Unknown,
#pragma warning restore CS0618
_ => throw new ArgumentException(FormattableString.Invariant($"Unsupported enum value '{result}'"))
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

namespace Microsoft.Omex.Extensions.Abstractions.Activities.Processing
{
/// <summary>
/// Activity does not have methods to extract tags efficiently, so we need to expose keys to provide ability of extracting tags
/// </summary>
public static class ActivityTagKeys
{
/// <summary>
/// Activity result tag key
/// </summary>
public static string Result { get; } = "Result";

/// <summary>
AndreyTretyak marked this conversation as resolved.
Show resolved Hide resolved
/// Activity sub type tag key
/// </summary>
public static string SubType { get; } = "SubType";


/// <summary>
/// Activity metadata tag key
/// </summary>
public static string Metadata { get; } = "Metadata";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

using System.Diagnostics;

namespace Microsoft.Omex.Extensions.Abstractions.ReplayableLogs
namespace Microsoft.Omex.Extensions.Abstractions.Activities.Processing
{
/// <summary>
/// Provides activities
/// </summary>
/// <remarks>This interface would be deleted after move to net 5.0, since inheritance won't be a supported extension model for Activity</remarks>
public interface IActivityProvider
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System.Diagnostics;

namespace Microsoft.Omex.Extensions.Abstractions.Activities.Processing
{
/// <summary>
/// Interface to monitor activity start
/// </summary>
public interface IActivityStartObserver
{
/// <summary>
/// Method will be called after activity start
/// </summary>
void OnStart(Activity activity, object? payload);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System.Diagnostics;

namespace Microsoft.Omex.Extensions.Abstractions.Activities.Processing
{
/// <summary>
/// Interface to monitor activity stop
/// </summary>
public interface IActivityStopObserver
{
/// <summary>
/// Method will be called after activity stop
/// </summary>
void OnStop(Activity activity, object? payload);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
// Licensed under the MIT license.

using System.Threading.Tasks;
using Microsoft.Omex.Extensions.Abstractions;

namespace Microsoft.Omex.Extensions.TimedScopes
namespace Microsoft.Omex.Extensions.Abstractions.Activities
{
/// <summary>
/// Extensions for Task to wrap them in TimedScope
Expand All @@ -18,7 +17,7 @@ public static async ValueTask<TResult> WithTimedScope<TResult>(this ValueTask<TR
{
using TimedScope timedScope = provider.CreateAndStart(definition, TimedScopeResult.SystemError);
TResult result = await task.ConfigureAwait(false);
timedScope.Result = TimedScopeResult.Success; // set TimedScope result to success in case if task completed properly (without exception)
timedScope.SetResult(TimedScopeResult.Success); // set TimedScope result to success in case if task completed properly (without exception)
return result;
}

Expand Down
51 changes: 51 additions & 0 deletions src/Extensions/Abstractions/Activities/TimedScope.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;
using System.Diagnostics;

namespace Microsoft.Omex.Extensions.Abstractions.Activities
{
/// <summary>
/// Logs duration of activity
/// </summary>
/// <remarks>This class will be replaced with Activity after move to net 5, since it will be trackable and disposable</remarks>
public class TimedScope : IDisposable
{
/// <summary>
/// Creates TimedScope instance
/// </summary>
/// <param name="activity">activity connected to this timedscope</param>
/// <param name="result">TimedScope initial result</param>
public TimedScope(Activity activity, TimedScopeResult result)
{
Activity = activity;
this.SetResult(result);
}


/// <summary>
/// Starts TimedScope activity
/// </summary>
public TimedScope Start()
{
s_listener.StartActivity(Activity, this);
return this;
}


/// <summary>
/// Stop TimedScope and log informations about it
/// </summary>
public void Stop() => s_listener.StopActivity(Activity, this);


internal Activity Activity { get; }
AndreyTretyak marked this conversation as resolved.
Show resolved Hide resolved


void IDisposable.Dispose() => Stop();


private static readonly DiagnosticListener s_listener = new DiagnosticListener("TimedScopesListener");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System;

namespace Microsoft.Omex.Extensions.Abstractions
namespace Microsoft.Omex.Extensions.Abstractions.Activities
{
/// <summary>
/// Store Timed Scope name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System;
using System.Runtime.Serialization;

namespace Microsoft.Omex.Extensions.TimedScopes
namespace Microsoft.Omex.Extensions.Abstractions.Activities
{
/// <summary>
/// Defines the possible scope results
Expand All @@ -21,7 +21,7 @@ public enum TimedScopeResult : int
/// </summary>
/// <remarks>Result should always be set to one of the other values explicitly. Unknown causes an error to be logged, and the scope is assumed failed.</remarks>
[EnumMember]
[Obsolete("Default value, not to be used explicitly", error: true)]
[Obsolete("Default value, not to be used explicitly", error: false)]
Unknown = 0,


Expand Down
Loading